【发布时间】:2020-09-18 20:18:32
【问题描述】:
我正在努力学习汇编。我反汇编了一个简单的 C 程序,并用 gdb 对其进行了调试。但我注意到的一件事是值的移动非常频繁。
0x0000555555555231 <+0>: push rbp
0x0000555555555232 <+1>: mov rbp,rsp
0x0000555555555235 <+4>: sub rsp,0x20
0x0000555555555239 <+8>: mov QWORD PTR [rbp-0x18],rdi
0x000055555555523d <+12>: mov QWORD PTR [rbp-0x20],rsi
0x0000555555555241 <+16>: mov rax,QWORD PTR [rbp-0x18]
0x0000555555555245 <+20>: mov rdi,rax
0x0000555555555248 <+23>: call 0x5555555551d9 <get_file_size>
rdi 的值在 rbp-0x18 () 处移入堆栈,rsi 的值在 rbp-0x20 (+12) 处移入堆栈。然后 rbp-0x18 处的值被移动到 rax(+16),它将再次移动到 rdi(+20)。为什么这样做?为什么不直接使用 rdi 或至少将 rbp-0x18 直接移动到 rdi,而不是通过 rax(在 处)?这可以将指令保存在 +20
【问题讨论】:
-
编译时尝试启用优化。使用
gcc,尝试指定-O3,看看你会得到什么。 -
我使用godbolt.org来查看代码和优化之间的区别,这可以帮助你
-
它将传入的参数保留在堆栈中(供以后使用,或者如果未优化,则仅仅因为它是函数的基本构造的一部分),然后使用其中一个进行嵌套调用参数,因为该参数存在于堆栈中(未优化),它需要从堆栈中读取它。推送和调用是函数构建中的两个独立子结构。堆栈帧,然后保存参数,然后进行调用,这里分别表示了三个不同的东西。
标签: c assembly disassembly instructions