我正在尝试分配变量来注册这里是代码:
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和this OP,但它没有回答我的问题。
注意:
答案 0 :(得分:5)
为什么我不能将8位变量移动到更大的16位寄存器中?
因为机器代码MOV
指令需要源操作数和目标操作数大小相同。这是必需的,因为MOV
指令本身并未指定如何填充较大目标寄存器的剩余位。
为了允许不同大小的移动操作,英特尔在80386 CPU中添加了MOVZX
和MOVSX
,这允许更小的源操作数(目标始终是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
答案 1 :(得分:0)
您正在使用汇编程序来跟踪如何声明符号以确定要使用的操作数大小。
var1
不是8位地址,它是指向两个8位变量中第一个的16位地址(不包括段)。因此汇编程序错误消息措辞严重且令人困惑。
NASM会按照你的说法做,并做16位负载。您会在var1
中找到bl
,在var2
找到bh
。大概你可以编写mov bx, word [var1]
或word ptr
或其他什么来让你的汇编程序发出16位负载。
(实际上,NASM会将mov BX, var1
汇集到mov r16, imm16
中,将地址放入寄存器。为了保持一致性,请始终在内存引用周围使用[]
。因为它适用于NASM和MASM英特尔语法的变体。但NASM不支持编写mov-immediate表单的mov BX, offset var1
语法。)