6

在查看 gdb 输出并查看程序集调用时,通常我可以找到一个使用硬编码值的命令来确定寄存器是从右到左加载还是反之亦然。

通常类似于以下内容:

  sub     rsp, 16

或者

  sub     16, rsp 

但其他时候,没有像上面这样的值是可见的。我所看到的只是如下调用:

(gdb) disassemble
 Dump of assembler code for function main:
 0x0000000100000f54 <main+4>:    mov    $rdi,%r15
 0x0000000100000f59 <main+9>:    mov    $rsi,%r14
 0x0000000100000f60 <main+16>:   mov    $rdx,%r13
 0x0000000100000f67 <main+23>:   mov    $ecx,$r12d
 End of assembler dump.

如何确定值是从左到右处理还是反之亦然?

4

1 回答 1

16

通常,Gnu 工具使用 AT&T 语法。您可以通过小符号的存在来判断它是 AT&T 语法,例如$前面的文字和%前面的寄存器。例如,这条指令:

sub    $16, %rax

显然是在使用 AT&T 语法。它从寄存器中的值中减去 16 rax,然后将结果存储回rax.

在 AT&T 语法中,目标操作数在右边

insn   source, destination     # AT&T syntax

还有英特尔语法。这在 Windows 平台上无处不在,通常也可作为 Gnu/Linux 工具的一个选项。英特尔语法是朴素的——<em>例如:

sub   rax, 16

这与上面的 AT&T 指令相同——它从rax寄存器中的值中减去 16,然后将结果存储回rax寄存器中。

在 Intel 语法中,目标操作数总是在左边

insn  destination, source     ; Intel syntax

要绝对确定您拥有哪个版本,您需要检查反汇编器/调试器的设置,并查看它配置为使用的语法,但通常仅通过查看来一眼就知道是非常简单的看看是否有符号装饰(AT&T 语法的死胡同)。

概括:

  • 如果寄存器有%前缀 → AT&T 语法 →src, dst顺序。
  • 否则,朴素的寄存器→英特尔语法→dst, src顺序。

如果您最终以某种方式查看了不使用任何寄存器 (???) 的代码,另一个很好的启发式线索是 Intel 语法会将大小说明符(如DWORDQWORDBYTE)添加到关联的操作数,而 AT&T 语法将将后缀(l, q,b等)附加到指令助记符本身。

于 2017-06-22T08:26:12.030 回答