How can I fix the problem of moving 8 bit value to the BX register (16 bit)?
mov al, 10h
mov bx, al
for this I get:
operands do not match: 16 bit and 8 bit register
The answer depends on whether you want to zero extend or sign extend the value and on whether you can or cannot use instructions available starting with the 80386. For better performance, the 80386 or later code should be used if movzx
and movsx
are available.
Zero the whole thing, then move to the low half.
xor bx, bx
mov bl, al
(Or equivalently, but less efficient on modern CPUs, xor bh, bh
or mov bh,0
to zero the upper 8 before or after replacing the low 8. mov bh,0
is still a 2-byte instruction but doesn't write FLAGS.)
Without movsx
, you probably want to use cbw
which only works with AL
-> AX
. The simplest way overwrites AH
before copying to BX
, since your value was already in AL
.
cbw ; AH = 0 or 0xFF according to top bit of AL
mov bx, ax
If you want to preserve AH
, you could copy the old AX
first then swap after cbw
:
mov bx, ax ; save the old AH (and AL)
cbw ; sign-extend AL into AX
xchg bx, ax ; BX = sign-extended result, restore original AX
Saving instructions on 8086 can involve planning what you keep in which register so it's already in the right place for an instruction like cbw
or mul
that uses an implicit register. By 386, Intel added versions of some of these that work with any register.
Use movzx
.
movzx bx, al
For best performance, zero extend all the way to 32 bit.
movzx ebx, al
Use movsx
, which is like cbw
but works for any dst, src, even including a memory source.
movsx bx, al
If possible, sign extend all the way to 32 bit for better performance.
movsx ebx, al
Other methods: setting the top half with neg
/sbb
is also possible, and so are arithmetic shifts or logical shifts for sign or zero extension. (Especially if your value started in a register like AH). See MASM Assembly move 8 bit register to the 16 bit register (ie. mov cx, ch)