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

Cannot move 8 bit address to 16 bit register

我正在尝试将变量分配给注册这里是代码:

       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

但是如果将第 4 行替换为:

MOV BL, var1;

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

我已经提到了 this, this and this OP 但它没有回答我的问题。

注意:

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

您正在使用一个 assembler 来跟踪您如何声明符号以确定要使用的操作数大小。

var1 不是 8 位地址,它是指向两个 8 位变量中第一个的 16 位地址(不计算段)。因此 assembler 错误消息措辞不当且令人困惑。

NASM 会按照你说的去做,并进行 16 位加载。您会在 bl 中找到 var1,在 bh 中找到 var2。大概你可以写 mov bx, word [var1],或 word ptr 或其他什么,让你的 assembler 发出 16 位负载。

(实际上,NASM 会将 assemble mov BX, var1 放入 mov r16, imm16,将地址放入寄存器。始终在内存引用周围使用 [],为了保持一致性,因为它适用于 NASM 和英特尔语法的 MASM 变体。NASM 不支持用于编写 mov-immediate 形式的 mov BX, offset var1 语法。)

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

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

为了允许不同大小的移动操作,英特尔在 80386 CPU 中添加了 MOVZXMOVSX,这允许较小的源操作数(目标始终是 32 位寄存器). -SX 和 -ZX 后缀表示应该填充目标寄存器以前未使用的位。

在 16 位 Intel 处理器上,有指令 CBW(将字节转换为字),它会将符号从 8 位扩展到 16 位。不幸的是,这仅适用于累加器(寄存器 AL/AX),因此您必须执行以下操作:

mov al,var1
cbw
mov bx,ax

cbw 进行符号扩展。如果你的 var1 是未签名的,你可以这样做:

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

或者,正如 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