如何理解这段AT&T i386汇编代码片段?

3
请查看以下代码片段:
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    

我需要弄清楚每一行的意思,有点困惑。


@PeterCordes 那是一段 C++ 代码。我把它当作一次经验。没有返回值是有意为之的。 - Edee
关于what the heck is this?lea 0x1(%eax),%edx 加载了 eax 指向的值,加上一,然后将结果存储在 edx 中。换句话说,这是你的 num1++; 的一部分——随后的存储到内存完成它。 - 500 - Internal Server Error
我知道这是C++,&引用说明了这一点。但它不是一个成员函数,所以没有this指针。如果你在那个函数中做了auto tmp = this;,那么它将会是一个编译时错误。 - Peter Cordes
是的,这不是一个成员函数,我只是不明白为什么汇编从0x8(%ebx)而不是0x4(%ebx)开始。@PeterCordes - Edee
1
此外,call / add 是因为这是一个32位PIE,并且在禁用优化的情况下,GCC正在生成代码以获取指向GOT的指针。而您正在查看.o的反汇编,因此链接器尚未填充偏移量。请使用objdump -drwC(最好使用-Mintel,除非您真的喜欢AT&T语法)。或者更好的方法是查看编译器asm输出,而不是从二进制文件中反汇编。 - Peter Cordes
显示剩余8条评论
1个回答

3
   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节详细讲述了栈帧的结构。

System V i386 ABI Table 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接