组装我们需要结局吗?

Assembly do we need the endings?

在汇编 (att) 中,以下是合法的:

mov %rax, %rbx

等于:

movq %rax, %rbx

其中q表示第一个参数是64位,我的问题是:

这个q(或其他结尾)是否只是为了便于人类阅读,或者在某些情况下,不写q会给出错误的答案或与预期不同的结果,甚至使代码崩溃(非法命令) , 可以的话请举个例子

您询问的是操作数大小后缀。有两种情况:

  1. 对于许多指令,操作数的大小可以从操作数本身推断出来,通常是因为它们是特定大小的寄存器。这就像您的示例:mov %rax, %rbx 必须具有 64 位操作数大小,因为 %rax, %rbx 是 64 位寄存器。在这种情况下,后缀是可选的,无论您写mov %rax, %rbx还是movq %rax, %rbx,都会生成相同的机器码(48 89 c3)。是否选择包含它纯粹是风格问题(尽管人们肯定对哪种方式更好有意见)。

    如果您提供的后缀与操作数不一致,例如movl %rax, %rbx,汇编器会给出警告或错误。

  2. 在其他情况下,无法推断操作数大小。最常见的情况是一个操作数是立即数而另一个是内存引用。如果你从评论中为 ecm 的例子写 mov , (%rbx),它是模棱两可的:汇编程序应该发出一条指令来存储一个字节(机器代码 c6 03 01),还是一个字(两个字节,66 c7 03 01 00 ),或长型(四个字节,c7 03 01 00 00 00),或四元组(八个字节,48 c7 03 01 00 00 00)?所以在这种情况下需要一个后缀:你必须写 movb , (%rbx)movw , (%rbx) 等等。

    如果您在这种情况下省略后缀,最新的汇编程序版本至少应该警告您。有些人会因错误而中止;其他人可能会猜测操作数的大小或使用一些内置的默认值,正如彼得在下面评论的那样。一些较旧的汇编程序版本实际上会在没有警告的情况下恢复为默认值。

所以原则上,是的,在某些情况下和某些汇编程序中,省略后缀可能会导致“错误”代码。但是,广泛使用的 AT&T 语法汇编程序的当前版本至少会警告您。

然而还有另一种方式可以实现这种情况:假设您想将 5 添加到 32 位寄存器 eax (addl , %eax),但您输入错误并离开关了e。如果你习惯使用后缀,你会写 addl , %ax 并得到一个汇编错误,提醒你你的错误。如果你的风格是省略它们,你会写 add , %ax 并且代码会完美构建但会“错误”。