x86汇编堆栈布局混乱

时间:2013-11-28 02:05:30

标签: assembly x86 stack disassembly

我有两个不同的二进制文件,其main函数的反汇编开头如下:

 80483d4:   55                      push   %ebp
 80483d5:   89 e5                   mov    %esp,%ebp
 80483d7:   83 e4 f0                and    $0xfffffff0,%esp
 80483da:   83 ec 20                sub    $0x20,%esp
 80483dd:   8d 45 08                lea    0x8(%ebp),%eax
 80483e0:   89 44 24 1c             mov    %eax,0x1c(%esp)

另一个是这个:

 80483d4:   8d 4c 24 04             lea    0x4(%esp),%ecx            
 80483d8:   83 e4 f0                and    $0xfffffff0,%esp         
 80483db:   ff 71 fc                pushl  -0x4(%ecx)                
 80483de:   55                      push   %ebp                     
 80483df:   89 e5                   mov    %esp,%ebp    
...
 80483e6:   89 4d f0                mov    %ecx,-0x10(%ebp) 

第一个是在GNU / Linux 2.6.24下编译的,第二个是在GNU / Linux 2.6.9下编译的。在大多数情况下,我理解为0x4(%esp)作为返回地址,0x8(%esp)作为第一个参数。显然,第一个二进制文件使用0x8(%ebp) - 在对齐发生之前与0x8(%esp)相同 - 作为第一个参数,而第二个二进制文件使用0x4(%esp)作为第一个参数,它让我困惑为什么会这样做。这是因为它们是在不同版本的GNU / Linux下编译的吗?

1 个答案:

答案 0 :(得分:0)

似乎两者都引用了第一个参数。第一个示例中的8(%ebp)与第二个示例中的4(%esp)之间的位移差异的原因是,一个在保存ebp之前发生,而另一个发生在之后。

要完全清楚:

movl 4(%esp), %eax # here, the first argument is at esp + 4
push %ebp          # push has the effect of esp -= 4
movl %esp, %ebp
movl 8(%ebp), %eax # here, the first argument is at esp + 8 (or equivalently, ebp + 8)

另一个值得关注的是,在将堆栈指针保存到一个二进制文件中的ebp之前以及将其保存到另一个二进制文件中之后,完成对齐堆栈指针。这对我来说似乎很奇怪 - 我只能假设在后一种情况下,esp的旧值会在主要返回之前的某个时刻从ecx重新计算。