gcc 在不同位置存储变量的值

逆向工程 拆卸
2021-06-18 22:20:36

我在 Ubuntu 32bit 上使用 gcc 版本 4.6.3 使用命令编译了以下程序 gcc -ggdb -o test test.c


void test(int a, int b, int c, int d)
{
    int flag;
    char buffer[10];
flag = 31337; buffer[0] = 'a'; a = 5; } int main(void) { test(1, 2, 3, 4); return 0; }

上面的测试函数在gdb中的反汇编是:-


   0x08048404 <+0>:     push   ebp
   0x08048405 <+1>:     mov    ebp,esp
   0x08048407 <+3>:     sub    esp,0x28
   0x0804840a <+6>:     mov    eax,gs:0x14
   0x08048410 <+12>:    mov    DWORD PTR [ebp-0xc],eax
   0x08048413 <+15>:    xor    eax,eax
   0x08048415 <+17>:    mov    DWORD PTR [ebp-0x20],0x7a69
   0x0804841c <+24>:    mov    BYTE PTR [ebp-0x16],0x41
=> 0x08048420 <+28>:    mov    DWORD PTR [ebp-0x1c],0x5
   0x08048427 <+35>:    mov    eax,DWORD PTR [ebp-0xc]
   0x0804842a <+38>:    xor    eax,DWORD PTR gs:0x14
   0x08048431 <+45>:    je     0x8048438 
   0x08048433 <+47>:    call   0x8048320 <__stack_chk_fail@plt>
   0x08048438 <+52>:    leave
   0x08048439 <+53>:    ret

据我所知,箭头后面的汇编指令对应a = 5;于测试函数中的C指令所以地址[ebp-0x1c]应该代表变量的地址a
但是[ebp-0x1c]代表0xbffff2bc的地址是 ,变量的地址a0xbffff2e0
我不明白这两个地址如何不同。这是gcc完成的某种优化吗?

1个回答

由于您没有a在任何地方阅读,似乎 gcc 甚至都懒得从堆栈中读取它,并为它创建了一个局部变量。尝试替换a=5with a+=5,这样编译器必须读取变量,并且指令可能会更改为访问 [ebp+8],这是参数应该存储的位置。

这种行为的原因可能是 gcc 试图使 32 位代码生成更类似于 64 位版本,其中参数在寄存器中传递,如果编译器需要寄存器,则需要保存在堆栈指针下方,或者需要创建指向参数的指针。在 32 位上做同样的事情——至少有时——可能有助于开发人员在 32 位和 64 位优化器之间共享代码。