Cannot move 8 bit address to 16 bit register

Ven picture Ven · Nov 27, 2015 · Viewed 7.8k times · Source

I am trying to assign variable to register here is the code:

       ORG 100h

        var1 DB 10  ;
        var2 DB 20  ;

        MOV BX,var1 ; error : operands do not match: 16 bit register and 8 bit address
RET
END

But if swap the 4th line with:

MOV BL, var1;

it works. So my question is why can’t I move 8 bit variable into much larger 16 bit register?

I have already referred this, this and this OP but it does not answer my question.

NOTE:

  1. I am using emu8086 assembler
  2. I am new to assembly language so I apologise if it's a stupid question.

Answer

mcleod_ideafix picture mcleod_ideafix · Nov 27, 2015

why can’t I move 8 bit variable into much larger 16 bit register?

Becase the machine code MOV instruction needs both the source operand and destination operand to be the same size. This is needed because a MOV instruction by itself doesn't specify how to fill the remaining bits of the larger destination register.

To allow for different size move operations, Intel added MOVZX and MOVSX in the 80386 CPU, which allow a smaller source operand (the destination is always a 32 bit register). -SX and -ZX suffixes denotes what the previously unused bits of the destination register should be filled with.

On 16-bit Intel processors, there is the instruction CBW (Convert Byte to Word), which does a sign extend from 8 to 16 bits. Unfortunately, this only works for the accumulator (register AL/AX), so you'd have to do something like:

mov al,var1
cbw
mov bx,ax

cbw does a sign extension. If your var1 is unsigned, you can do simply as this:

mov bl,var1
xor bh,bh  ; equivalent to mov bh,0 but faster and only one byte opcode

Or, as Peter Cordes states:

xor bx,bx    ;clear the whole destination register
mov bl,var1  ;update the least significant byte of the register with the 8-bit value