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

Assembly 无法将8位地址移动到16位寄存器,assembly,x86,x86-16,emu8086,Assembly,X86,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 但如果将第四行替换为: MOV BL, var1; 它起作用了。所以我的问题是,为什么我不能将8位变量移动到更大的16位寄存器 我已经提到了O

我正在尝试分配要注册的变量,代码如下:

       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
但如果将第四行替换为:

MOV BL, var1;
它起作用了。所以我的问题是,为什么我不能将8位变量移动到更大的16位寄存器

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

注意:

  • 我使用的是emu8086汇编程序
  • 我不熟悉汇编语言,所以如果这是一个愚蠢的问题,我道歉

  • 您使用的是一个汇编程序,它跟踪您如何声明符号,以确定要使用的操作数大小

    var1
    不是一个8位地址,它是一个16位地址(不包括段),指向两个8位变量中的第一个。因此,汇编程序错误消息措辞糟糕,令人困惑

    NASM会照你说的做,然后进行16位加载。您可以在
    bl
    中找到
    var1
    ,在
    bh
    中找到
    var2
    。大概您可以编写
    mov-bx、word[var1]
    word-ptr
    或任何东西,以使汇编程序发出16位负载

    (实际上,NASM会将
    mov BX,var1
    组合成
    mov r16,imm16
    ,将地址放入寄存器。始终使用
    []
    围绕内存引用,以保持一致性,因为这适用于英特尔语法的NASM和MASM变体。不过,NASM不支持写入mov立即数形式的
    mov BX,offset var1
    语法。)

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

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

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

    在16位英特尔处理器上,有一条指令
    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
    
    或者,正如彼得·科尔德斯所说:

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

    您需要使用
    movzx
    movsx
    ,如果可以分别使用零或符号扩展进行移动。它可能在8086中不可用,在这种情况下,您需要像您所做的那样进入
    BL
    ,然后自己将
    BH
    归零。至于原因:因为他们是这样创建架构的:)@Jester:不是,只有cbw。我更新了标签wiki,其中有一个指向wikipedia的链接,其中有一个表格,列出了引入各种指令的时间。还有一篇关于在16位8086上学习asm是如何愚蠢的文章。但无论如何,一些主要的INSN8086缺失的是movzx/sx和bt*bit-manip.upvoting,这只是因为错误信息措辞糟糕且具有误导性。这里的答案并没有试图解释为什么这是一个错误,movzx在8086上也不起作用,但仍然存在。投票决定将其作为本文件的副本关闭,因为本文件有更详细的答案。
    xor bx,bx/mov bl,var1
    会更好,因为它更像是您希望在32位或64位模式下使用的好习惯用法之一(在使用较小部分之前将整个寄存器归零)。它打破了对完整寄存器的旧内容的错误依赖,但将上半部分和下半部分分别归零则不行。另外,
    movs/zxr16,r/m8
    是有效的。它对于64位dest reg也是有效的,但对于
    movzx
    则不鼓励这样做,因为它与32位dest的movzx相同。有一个新的操作码用于
    movsx r64,r/m32
    ,但不用于movzx。另外,
    mov-bh,bh
    是一个2字节指令,与
    mov-bh,0
    的代码大小相同。如果你要写BH,mov实际上更适合现代CPU上的8位寄存器。(但这两种方法都不好,而将整个16位寄存器的xor归零,就像我之前的评论一样。)