我对
movzx
在下面的示例中的表现有点困惑。 (请注意,我假设我的代码示例中使用的 print_int 函数有效,问题不存在,而是在我对 movzx
的理解中,因为这是我们的教授推荐的,据说它只是将寄存器中的内容打印为十进制数):
%include "../linux-ex/asm_io.inc"
extern printf
section .text
global main
main:
push ebp
mov ebp, esp
xor eax, eax
mov ax, [n1]
call print_int
leave
ret
section .data
n1 dw 01234h
这段 32 位架构上的 NASM 代码按预期打印出
4660
。如果我改变:
mov ax, [n1]
到
movzx ax, [n1]
我得到了
52
的输出。我知道尝试零扩展到 ax
没有任何意义,因为 n1
的大小也是 16 位,但我很惊讶它会产生不同的输出。在第二个示例中,前 8 位似乎被截断并设置为零,留下十六进制数:34
,即十进制 52
。为什么会出现这种情况?
当汇编器看到时
movzx ax, [n1]
它寻找适合此处使用的助记符和操作数的指令。 IE。具有助记符
movzx
的指令,其第一个操作数是 16 位寄存器,第二个操作数是内存操作数。唯一符合要求的 movzx
变体是
movzx r16, r/m8
这确实是 NASM 汇编此代码的目的。
与 MASM 相比,NASM 不跟踪交易品种的类型。虽然 MASM 可能会发出警告或导致汇编失败,因为
[n1]
具有字类型但用作字节类型的操作数,但 NASM 不会这样做。相反,如果操作数的大小不明确(即,如果有多个指令具有相同的助记符和操作数,但操作数大小不同),则必须使用 byte
、word
或 dword
等关键字显式指定操作数的大小.