5

我想知道如何在英特尔语法的某些指令中区分标签名称和寄存器名称。例如,call rdx通常意味着间接跳转,但如果我们rdx在同一个汇编文件中有标签怎么办?我相信它可以解释为直接跳转到rdx. 是否有任何符号告诉汇编程序哪个是哪个?

4

2 回答 2

3

是否有任何符号告诉汇编程序哪个是哪个?

这取决于您使用的汇编程序。没有通用的语法可以做到这一点。

然而,一些汇编程序具有区分标签和保留字的功能。例如,nasm 文档中的“3.1 NASM 源代码行的布局”部分指出,您可以在标签前面加上 a$以将其与寄存器区分开来:

一个标识符也可以加上前缀a $,表示它是作为一个标识符而不是一个保留字来读的;因此,如果您要链接的某个其他模块定义了一个名为 eax 的符号,您可以$eax在 NASM 代码中引用该符号以将该符号与寄存器区分开来

于 2019-08-22T09:26:34.687 回答
3

这取决于汇编程序。

我认为对于大多数人来说,寄存器名称优先,所以call rdx总是 RIP=RDX,而不检查是否存在同名的标签(或外部符号)。
AT&T 语法call *%rdx,而不是 AT&T call rdx

一些汇编器具有消除歧义的语法,但不同的汇编器之间没有标准语法

例如对于 NASM,这是符号名称与新 NASM 版本中的新寄存器名称冲突的副本吗?您可以在其中使用$eax名称来引用符号/标签eax,而不是寄存器。

对于 Euroassembler,您可以将 a 后缀:到名称上,以强制将其解释为符号,而不是寄存器,例如call rdx:. ( https://euroassembler.eu/eadoc/#SymbolName ),


使用 GAS代替.intel_syntax noprefix,您可以在寄存器名称上使用.intel_syntax prefixso 。%rdx

.intel_syntax没有操作数的意思.intel_syntax prefix

GAS 的 Intel 语法可能有点落后于 AT&T 语法的二等公民。这个问题显然不存在于 AT&T 语法 where %rdxis the register and rdxis the symbol 中。

.intel_syntax               # prefix is the default
rdx:
   call rdx                 # call rel32
   call %rdx                # call reg

.intel_syntax noprefix
   call rdx                 # call reg
   # I don't know how to write call rel32 to the label with noprefix

然后我们可以在 AT&T 语法中反汇编,以便更加清楚/明确地了解我们得到的内容。

$ gcc -c gas-symbol.s && objdump -d -Matt gas-symbol.o

0000000000000000 <rdx>:
   0:   e8 fb ff ff ff          callq  0 <rdx>
   5:   ff d2                   callq  *%rdx

0000000000000007 <with_noprefix>:
   7:   ff d2                   callq  *%rdx

对于整个文件,您可能通常不希望这样做,但是您可以切换到.att_syntax或切换到.intel_syntax prefix一行或块,然后切换回 normal .intel_syntax noprefix

于 2019-08-22T09:27:42.343 回答