如何理解这段 AT&T i386 汇编代码片段?
How to understand this AT&T i386 assembly code snippet?
请查看以下代码片段:
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 [=11=]x1,%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
我需要弄清楚每一行的意思,我有点困惑。
3: e8 fc ff ff ff call 4 <_Z3sumRiS_+0x4>
这不是调用的真正目的地,它是由链接器填充的。如果你运行objdump -dr sum.o
,你会发现它实际上是对__x86.get_pc_thunk.ax
的调用。以下add
同理,设置指向GOT的指针。 (这个函数不需要一个,但你编译时没有优化,默认情况下 -fpie
打开。)
详情请看Why does gcc generates strange code without flag -fno-pie?
System V i386 ABI, 2.2.2 节讲述了堆栈帧的结构。
所以你的堆栈框架看起来像这样:
0xc | num2 |
0x8 | num1 |
0x4 | return address |
0x0 | previous %ebp | <-- %ebp
剩下的说明,这里一步步分析。
// as num1 and num2 are references, they represents address in assembly
d: 8b 45 08 mov 0x8(%ebp),%eax // load num1 to %eax
10: 8b 00 mov (%eax),%eax // load *num1 to %eax
12: 8d 50 01 lea 0x1(%eax),%edx // put *num1 + 1 into %edx
15: 8b 45 08 mov 0x8(%ebp),%eax // load num1 to %eax
18: 89 10 mov %edx,(%eax) // save *num1 + 1 at num1
1a: 8b 45 0c mov 0xc(%ebp),%eax // same as above
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)
请查看以下代码片段:
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 [=11=]x1,%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
我需要弄清楚每一行的意思,我有点困惑。
3: e8 fc ff ff ff call 4 <_Z3sumRiS_+0x4>
这不是调用的真正目的地,它是由链接器填充的。如果你运行objdump -dr sum.o
,你会发现它实际上是对__x86.get_pc_thunk.ax
的调用。以下add
同理,设置指向GOT的指针。 (这个函数不需要一个,但你编译时没有优化,默认情况下 -fpie
打开。)
详情请看Why does gcc generates strange code without flag -fno-pie?
System V i386 ABI, 2.2.2 节讲述了堆栈帧的结构。
所以你的堆栈框架看起来像这样:
0xc | num2 |
0x8 | num1 |
0x4 | return address |
0x0 | previous %ebp | <-- %ebp
剩下的说明,这里一步步分析。
// as num1 and num2 are references, they represents address in assembly
d: 8b 45 08 mov 0x8(%ebp),%eax // load num1 to %eax
10: 8b 00 mov (%eax),%eax // load *num1 to %eax
12: 8d 50 01 lea 0x1(%eax),%edx // put *num1 + 1 into %edx
15: 8b 45 08 mov 0x8(%ebp),%eax // load num1 to %eax
18: 89 10 mov %edx,(%eax) // save *num1 + 1 at num1
1a: 8b 45 0c mov 0xc(%ebp),%eax // same as above
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)