无法将 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 但它没有回答我的问题。
注意:
- 我正在使用 emu8086 汇编程序
- 我是汇编语言的新手,所以如果这是一个愚蠢的问题,我深表歉意。
您正在使用一个 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 中添加了 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
我正在尝试将变量分配给注册这里是代码:
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 但它没有回答我的问题。
注意:
- 我正在使用 emu8086 汇编程序
- 我是汇编语言的新手,所以如果这是一个愚蠢的问题,我深表歉意。
您正在使用一个 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 中添加了 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