【问题标题】:Can't size instruction无法调整大小说明
【发布时间】:2020-08-12 02:58:44
【问题描述】:

我想知道为什么有些汇编指令可以推断出来,而有些则不能。例如,在以下程序中,我有:

.globl main
main:
    push %rbp
    mov %rsp, %rbp
    mov $8, -8(%rbp)
    mov -8(%rbp), %rax
    pop %rbp
    ret

我收到以下错误:

stack.s:5:错误:没有给出指令助记符后缀,也没有寄存器操作数;无法调整指令大小

但是,如果我将:第 5 行更改为:

movq $8, -8(%rbp)

它运行没有错误。所有其他操作如何推断大小,但特定指令却不能?

【问题讨论】:

  • 因为mov $8, -8(%rbp) 说将值 8 移动到内存位置,但值是 8 有多大。它是 8 的字节,0x08 的字长,0x08 的四字0x08?这就是为什么您必须指定大小,因为大小不能由任一操作数确定。在其他情况下,操作数之一是寄存器并且寄存器具有已知宽度。比如RAX是64位寄存器EAX是32位寄存器,AX是16位寄存器,AL/AH是8位寄存器

标签: assembly x86 gnu-assembler att


【解决方案1】:

提示在消息中:“没有寄存器操作数”。

所有其他指令都有一个寄存器作为操作数,汇编器知道寄存器有多大。例如,mov %rax, -8(%rbp) 必须是四字移动(8 个字节),因为%rax 是一个 64 位寄存器。同样,mov %eax, -8(%rbp)mov %ax, -8(%rbp)mov %al, -8(%rbp) 将是长字/字/字节移动(4 / 2 / 1 个字节)。因此,这些说明的大小后缀是可选的。

但是直接常量$8 没有固有大小,所以除非你告诉它,否则汇编器无法知道你想要什么大小。

【讨论】:

  • 请注意,GAS 在add $8, -8(%rbp) 上很遗憾没有 错误。 (Binutils 2.34) 相反,它选择 dword 操作数大小作为默认值。我想我读过历史上 AT&T 的 unix 汇编器就是这样做的,但这是保持这种危险行为的可怕原因。更不用说不一致了,mov 和 add 都有从字节到 qword 的所有大小。也许有人应该报告错误,这可能是无意的行为。
  • 记得我在哪里看到的:in the GAS manual请注意,这与 AT&T Unix 汇编器不兼容,后者假定缺少助记符后缀意味着操作数过长。 (这种不兼容性不会影响编译器输出,因为编译器总是明确指定助记符后缀。) 所以我认为这是一个错误,不是故意的。
猜你喜欢
  • 2012-05-28
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 2018-12-11
  • 2020-09-25
  • 2012-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多