为什么输出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;
}
答案 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)
您假设编译器已经打包了所有内容(而不是将内容放在特定的对齐边界上),并且您还假设编译器没有内联函数,或进行任何其他优化或转换。
总之,您不能对此类事情做出任何假设,也不能依赖任何特定行为。