Igo*_*sky 38

AT&T语法将movzx英特尔指令助记符分成不同的助记符,用于不同的源大小(movzbvs. movzw).在Intel语法中,它是:

movzx eax, byte ptr [eax+ecx+1]
Run Code Online (Sandbox Code Playgroud)

即从eax + ecx + 1的内存加载一个字节,并将零扩展到完整寄存器.

顺便说一句,大多数GNU工具现在都有一个开关或配置选项来选择英特尔语法.(例如,objdump -Mintel或者gcc -S -masm=intel,虽然后者影响编译inline-asm时使用的语法).如果你不做AT&T组装生活,我肯定会建议调查一下.有关更多文档和指南,另请参阅标记wiki.

  • @MariusGedminas 您可能可以显式地将 rax 与 movzbq 一起使用,但是对 32 位寄存器的任何操作都会将前 32 位清零,因此实际上 movzbl 到 eax 将扩展到 rax。 (3认同)
  • 假设我正在查看 64 位 x86_64 代码中的 `movzbl`,“零扩展到完整寄存器”是指 %eax 还是完整的 %rax? (2认同)

Cir*_*四事件 20

最小的例子

mov $0x01234567, %eax
mov $1, %bl
movzbl %bl, %eax
/* %eax == 0000 0001 */

mov $0x01234567, %eax
mov $-1, %bl
movzbl %bl, %eax
/* %eax == 0000 00FF */
Run Code Online (Sandbox Code Playgroud)

使用断言向上游运行GitHub.

助记符是:

  • MOV
  • 零延伸
  • 字节(8位)
  • 到长(32位)

还有其他尺寸的版本:

  • movzbw:字节(8位)到Word(16位)
  • movzwl:字(16位)到长(32位)

与大多数GAS指令一样,在处理寄存器时可以省略最后一个大小字符:

movzb %bl, %eax
Run Code Online (Sandbox Code Playgroud)

但我不明白为什么我们不能省略前一封信,例如以下失败:

movz %bl, %eax
Run Code Online (Sandbox Code Playgroud)

为什么不在它们是寄存器mov和英特尔语法的情况下从操作数的大小推导出它?

如果您使用错误大小的寄存器,则无法编译,例如:

movzb %ax, %eax
Run Code Online (Sandbox Code Playgroud)