进程的堆栈布局

时间:2011-04-04 09:14:49

标签: c

为什么输出44而不是12,& x,eip,ebp和& j应该是代码的堆栈布局 如下所示,如果是,那么它必须有12作为输出,但我得到它44? 所以帮助我理解这个概念,尽管每个执行瞬间重新定位基指针,相对必须保持不变,不应该是12?

int main() {
    int x = 9;
    // printf("%p is the address of x\n",&x);
    fun(&x );
    printf("%x is the address of x\n", (&x));
    x = 3;
    printf("%d x is \n",x);
    return 0;
}

int fun(unsigned int *ptr) {    
    int j;
    printf("the difference is  %u\n",((unsigned int)ptr -(unsigned int) &j));
    printf("the address of j is %x\n",&j);

    return 0;
}

2 个答案:

答案 0 :(得分:4)

不,它应该为12.它应该是什么。 ISO标准对于如何在堆栈上排列事物几乎没有什么可说的。实现在移动内容和插入填充以提高效率方面有很大的余地。

如果你通过编译器传递了一个生成汇编程序代码的选项(例如使用gcc -S),那么这里会发生什么变得明显。

fun:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $40, %esp            ;; this is quite large (see below).
    movl    8(%ebp), %edx
    leal    -12(%ebp), %eax
    movl    %edx, %ecx
    subl    %eax, %ecx
    movl    %ecx, %eax
    movl    %eax, 4(%esp)
    movl    $.LC2, (%esp)
    call    printf
    leal    -12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC3, (%esp)
    call    printf
    movl    $0, %eax
    leave
    ret

似乎gcc正在预生成下一个堆栈帧(一个下降到printf)作为fun函数的序言的一部分。那是在这种情况下。您的编译器可能正在执行完全不同的操作但最重要的是:只要不违反标准,实施就可以做到它想做的事情。

顺便提一下,这是来自优化级别0的代码,它给出了48的差异。当我使用gcc的疯狂优化级别3时,我得到的差异为4.再次,完全可以接受,gcc通常会做一些非常令人印象深刻的在那个级别进行优化。

答案 1 :(得分:4)

您假设编译器已经打包了所有内容(而不是将内容放在特定的对齐边界上),并且您还假设编译器没有内联函数,或进行任何其他优化或转换。

总之,您不能对此类事情做出任何假设,也不能依赖任何特定行为。