我想知道如何在英特尔语法的某些指令中区分标签名称和寄存器名称。例如,call rdx
通常意味着间接跳转,但如果我们rdx
在同一个汇编文件中有标签怎么办?我相信它可以解释为直接跳转到rdx
. 是否有任何符号告诉汇编程序哪个是哪个?
2 回答
是否有任何符号告诉汇编程序哪个是哪个?
这取决于您使用的汇编程序。没有通用的语法可以做到这一点。
然而,一些汇编程序具有区分标签和保留字的功能。例如,nasm 文档中的“3.1 NASM 源代码行的布局”部分指出,您可以在标签前面加上 a$
以将其与寄存器区分开来:
一个标识符也可以加上前缀a
$
,表示它是作为一个标识符而不是一个保留字来读的;因此,如果您要链接的某个其他模块定义了一个名为 eax 的符号,您可以$eax
在 NASM 代码中引用该符号以将该符号与寄存器区分开来
这取决于汇编程序。
我认为对于大多数人来说,寄存器名称优先,所以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 prefix
so 。%rdx
.intel_syntax
没有操作数的意思.intel_syntax prefix
。
GAS 的 Intel 语法可能有点落后于 AT&T 语法的二等公民。这个问题显然不存在于 AT&T 语法 where %rdx
is the register and rdx
is 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
。