assemblyx86-16emu8086sign-extensionzero-extension

MOV 8 bit to 16 bit register (al to bx)


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 

Solution

  • 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 extend on an 8086 or 80286

    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.)

    sign extend on an 8086 or 80286

    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.


    zero extend on an 80386 or newer

    Use movzx.

    movzx bx, al
    

    For best performance, zero extend all the way to 32 bit.

    movzx ebx, al
    

    sign extend on an 80386 or newer

    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)