无法将8位地址移动到16位寄存器

Ven*_*Ven 4 x86 assembly x86-16 emu8086

我试图分配变量来注册这里是代码:

       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
Run Code Online (Sandbox Code Playgroud)

但如果换掉第4行:

MOV BL, var1;
Run Code Online (Sandbox Code Playgroud)

有用.所以我的问题是为什么不能8位变量移动到更大的16位寄存器中

我已经提到了这个,这个这个 OP,但它没有回答我的问题.

注意:

  1. 我正在使用emu8086汇编程序
  2. 我是汇编语言的新手,所以如果这是一个愚蠢的问题,我道歉.

mcl*_*fix 5

为什么我不能将8位变量移动到更大的16位寄存器中?

因为机器代码MOV指令需要源操作数和目标操作数大小相同.这是必需的,因为MOV指令本身并未指定如何填充较大目标寄存器的剩余位.

为了允许不同尺寸的移动操作,Intel增加MOVZXMOVSX80386的CPU,这允许更小的源操作数中(目标始终是一个32位寄存器).-SX和-ZX后缀表示应填充目标寄存器的先前未使用的位.

在16位Intel处理器上,有CBW一条指令(Convert Byte to Word),它的符号范围从8位扩展到16位.不幸的是,这仅适用于累加器(寄存器AL/AX),因此您必须执行以下操作:

mov al,var1
cbw
mov bx,ax
Run Code Online (Sandbox Code Playgroud)

cbw签名延期.如果你var1是未签名的,你可以这样做:

mov bl,var1
xor bh,bh  ; equivalent to mov bh,0 but faster and only one byte opcode
Run Code Online (Sandbox Code Playgroud)

或者,正如Peter Cordes所述:

xor bx,bx    ;clear the whole destination register
mov bl,var1  ;update the least significant byte of the register with the 8-bit value
Run Code Online (Sandbox Code Playgroud)

  • `xor bx,bx/mov bl,var1`会更好,因为它更像是你想要在32或64位模式下使用的好习惯之一(在使用较小的部分之前将整个寄存器归零).它打破了对完整寄存器的旧内容的错误依赖性,但是分别将上半部分和下半部分归零不会.另外,`movs/zx r16,r/m8`有效.它也适用于64位dest reg,但是对于'movzx'不鼓励,因为它与具有32位dest的movzx相同.`movsx r64,r/m32`有一个新的操作码,但不适用于movzx. (3认同)