【发布时间】:2020-08-19 17:11:03
【问题描述】:
请查看以下代码sn-ps:
int& sum(int& num1, int& num2) {
num1++;
num2++;
}
00000000 <_Z3sumRiS_>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: e8 fc ff ff ff call 4 <_Z3sumRiS_+0x4> // why here is a jump
8: 05 01 00 00 00 add $0x1,%eax
// why 0x8, my understanding is there are in total 3 parameters
// num2 -- 0xc(%ebp), num1 -- 0x8(%ebp), this -- 0x4(%ebp)
// am I right????
d: 8b 45 08 mov 0x8(%ebp),%eax
10: 8b 00 mov (%eax),%eax
12: 8d 50 01 lea 0x1(%eax),%edx // what the heck is this?
15: 8b 45 08 mov 0x8(%ebp),%eax
18: 89 10 mov %edx,(%eax)
1a: 8b 45 0c mov 0xc(%ebp),%eax
1d: 8b 00 mov (%eax),%eax
1f: 8d 50 01 lea 0x1(%eax),%edx
22: 8b 45 0c mov 0xc(%ebp),%eax
25: 89 10 mov %edx,(%eax)
27: 90 nop
28: 5d pop %ebp
29: c3 ret
我需要弄清楚它的每一行的含义,我有点困惑。
【问题讨论】:
-
这不是 C++ 成员函数,因此没有
this参数。保存的 EBP 上方的栈槽是返回地址。此外,它具有未定义的行为,因为您脱离了非void函数的末尾。 GCC-O0似乎是故意评估返回值寄存器中具有副作用的最后一个表达式,所以如果你只关心gcc -O0,这个 sort of works as returningnum2++。它已完全损坏,无法用于任何其他用途。 -
@PeterCordes 那是一段 C++ 代码。我把它当作一种体验。故意没有返回值。
-
对于
what the heck is this?,lea 0x1(%eax),%edx加载eax指向的值,加一,然后将结果存入edx。 IOW,这是您的num1++;的一部分 - 随后的内存存储完成了它。 -
查看具有未定义行为的代码的编译器输出可能会令人困惑,我不建议您首先使用它。请参阅 How to remove "noise" from GCC/clang assembly output? - godbolt.org 可以将源代码行与 asm 块匹配。
-
另外,
call/add是因为这是一个 32 位 PIE,并且禁用优化的 GCC 正在编写代码以获取指向 GOT 的指针。而且您正在查看.o的反汇编,因此链接器尚未填充偏移量。使用objdump -drwC(最好使用-Mintel,除非你真的喜欢AT&T语法)。或者更好的是,查看编译器 asm 输出而不是从二进制反汇编。