gcc用我的堆栈做什么?

时间:2010-11-09 03:07:33

标签: gcc assembly stack policy

编辑真正的问题是在帖子的最后 我试图解决gcc如何管理堆栈大小但我有一些问题我找不到答案。

当我在另一个函数中调用函数时,Gcc会做一些奇怪的事情。它分配额外的字节,我不明白为什么。

以下是最简单的C代码:

int f(){
    int i =12;
    return 0;
}


int main(void){
    f();
    return 0;
}

然后是gdb产生的f()的disass:

0x08048386 <+0>:     push   %ebp
0x08048387 <+1>:     mov    %esp,%ebp
0x08048389 <+3>:     sub    $0x10,%esp <- this part
0x0804838c <+6>:     movl   $0xc,-0x4(%ebp)
0x08048393 <+13>:    mov    $0x0,%eax
0x08048398 <+18>:    leave  
0x08048399 <+19>:    ret  

好的,我不知道。 gcc按原样生成16字节的对齐堆栈 一个int(所以4个字节)gcc在堆栈上为i分配16个字节。

但是只要我在f()中调用一个函数,我就不会得到gcc正在做的事情。 这是新的C代码:

int g(int i){
    i=12;
    return i;
}

int f(){
    int i =12;
    g(i);
    return 0;
}


int main(void){
    f();
    return 0;
}

然后f()disass:

0x08048386 <+0>:     push   %ebp
0x08048387 <+1>:     mov    %esp,%ebp
0x08048389 <+3>:     sub    $0x14,%esp <- Here is my understanding
0x0804838c <+6>:     movl   $0xc,-0x4(%ebp)
0x08048393 <+13>:    mov    -0x4(%ebp),%eax
0x08048396 <+16>:    mov    %eax,(%esp)
0x08048399 <+19>:    call   0x8048374 <g>
0x0804839e <+24>:    mov    $0x0,%eax
0x080483a3 <+29>:    leave  
0x080483a4 <+30>:    ret

然后gcc分配4个额外字节,而没有比f()更多的变化 正在呼唤g()。

当我玩更多功能时,这可能是最糟糕的。

所以你们任何人都知道这个额外的字节是什么,gcc是什么 堆栈分配政策?

提前谢谢。

编辑:真实问题

好的抱歉,我写的问题太快,实际上它没关系 sub 0x14%esp我真正理解的是这段代码:

int f(){
    char i[5];
    char j[5];
    i[4]=0;
    j[4]=0;
    strcpy(i,j);
    return 0;
}


int main(void){
    f();
    return 0;
}

然后f()的暗示:

0x080483a4 <+0>:     push   %ebp
0x080483a5 <+1>:     mov    %esp,%ebp
0x080483a7 <+3>:     sub    $0x28,%esp
0x080483aa <+6>:     movb   $0x0,-0x9(%ebp)
0x080483ae <+10>:    movb   $0x0,-0xe(%ebp)
0x080483b2 <+14>:    lea    -0x12(%ebp),%eax
0x080483b5 <+17>:    mov    %eax,0x4(%esp)
0x080483b9 <+21>:    lea    -0xd(%ebp),%eax
0x080483bc <+24>:    mov    %eax,(%esp)
0x080483bf <+27>:    call   0x80482d8 <strcpy@plt>
0x080483c4 <+32>:    mov    $0x0,%eax
0x080483c9 <+37>:    leave  
0x080483ca <+38>:    ret

堆栈看起来像那样:

[oldip] [oldebp] [Extra(8B)] [Arrays(10B)] [Rearrange stack(14B)] [Argument1(4B)] [Argument2(4B)]

在这里,我们看到在保存的ebp和。之间有8个额外的字节 局部变量。所以这是我的理解。

对于张贴太快而感到抱歉,仍然感谢你的快速 答案。

2 个答案:

答案 0 :(得分:0)

0x08048386 <+0>:     push   %ebp
0x08048387 <+1>:     mov    %esp,%ebp
0x08048389 <+3>:     sub    $0x14,%esp <- include 0x10 bytes for stack alignment and 4 byte for 1 parameter
0x0804838c <+6>:     movl   $0xc,-0x4(%ebp)
0x08048393 <+13>:    mov    -0x4(%ebp),%eax
0x08048396 <+16>:    mov    %eax,(%esp)
0x08048399 <+19>:    call   0x8048374 <g>
0x0804839e <+24>:    mov    $0x0,%eax
0x080483a3 <+29>:    leave  
0x080483a4 <+30>:    ret

如你所见,它分配16个字节包含i和堆栈对齐,加上4个字节用于一个参数,堆栈将如下所示。

00 7f 7c 13              --> return from call address
00 00 00 00              --> this one for parameter when call g(i)  --> low address
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 0C ---> i       (ignore about edian)        --> high address 

答案 1 :(得分:0)

我认为在第一种情况下,4个字节用于调用g()时所需的一个参数。在第二种情况下,调用strcpy()时两个参数需要两个4字节的字。用三个参数调用一个虚函数,看它是否变为12个字节。

相关问题