关于入栈、出栈,栈顶栈底之类的分析见
函数调用的压栈出栈过程分析
下面继续分析C/C++的内存分布。
虽然0x10比一个变量需要的4个地址大了一些,但是0x10应该是规定的最小单位了。假如你要用的空间刚好是它的整数倍,其实是不浪费一分钱栈空间的,下边做一个数组,证明栈空间大小刚好是所有非静态变量占用空间的大小。
这里可以先无视hello的声明,它不在栈空间,后面会分析。
x6 #include<stdio.h> x x7 int main(){ x x9 static int hello; x B+>x11 int array[100] = {7,4,1}; x x16 return 0; x x17 }
下边是汇编代码:比普通变量情况下复杂些,多用了一些寄存器,多了一些push、pop操作,还有rep指令。
x0x8048394 <main> push %ebp x x0x8048395 <main+1> mov %esp,%ebp x x0x8048397 <main+3> push %edi x x0x8048398 <main+4> push %ebx x x0x8048399 <main+5> sub $0x190,%esp x B+>x0x804839f <main+11> lea -0x198(%ebp),%ebx x x0x80483a5 <main+17> mov $0x0,%eax x x0x80483aa <main+22> mov $0x64,%edx x100个变量(应该还有个标志类型大小是4的东西吧) x0x80483af <main+27> mov %ebx,%edi x x0x80483b1 <main+29> mov %edx,%ecx x x0x80483b3 <main+31> rep stos %eax,%es:(%edi) x x0x80483b5 <main+33> movl $0x7,-0x198(%ebp) x初始化了三个数。 x0x80483bf <main+43> movl $0x4,-0x194(%ebp) x x0x80483c9 <main+53> movl $0x1,-0x190(%ebp) x x0x80483d3 <main+63> mov $0x0,%eax x x0x80483d8 <main+68> add $0x190,%esp x0x80483de <main+74> pop %ebx x x0x80483df <main+75> pop %edi x x0x80483e0 <main+76> pop %ebp x x0x80483e1 <main+77> ret x x
(gdb) print $esp $1 = (void *) 0xbffff480 (gdb) print $ebp $2 = (void *) 0xbffff618
我们都知道,”加了static就延长了变量的生命周期到程序结束“,或者还知道”加了static的变量地址不太一样“!
确实,地址变了,静态变量不在栈里。
int main(){ static int hello; int top; return 0; }地址,top在栈中,而hello不在
(gdb) print &top $3 = (int *) 0xbffff614 (gdb) print &hello $4 = (int *) 0x8049614栈大小是0x10
(gdb) print $esp $3 = (void *) 0xbffff608 (gdb) print $ebp $4 = (void *) 0xbffff618
#include<stdio.h> int main(){ hello = 4; static int hello; return 0; }连初学者都认为这样不可能,但是,如果我换一种写法呢?
#include<stdio.h> static int hello; int main(){ hello = 4; return 0; }这样大家就都认可了吧!
x0x8048394 <main> push %ebp x x0x8048395 <main+1> mov %esp,%ebp x B+>x0x8048397 <main+3> movl $0x4,0x8049614 x x0x80483a1 <main+13> mov $0x0,%eax x x0x80483a6 <main+18> pop %ebp x x0x80483a7 <main+19> ret x
main内声明肯定是看不到的,直接用了一下而已,如果没有那个赋值语句,main内部什么命理你个都看不到,直接就结束了。
#include<stdio.h> int main(){ int *ptr = 0x8049614; printf("%d\n",*ptr); static int hello = 100; return 0; }print *ptr = 0(期望100)
#include<stdio.h> //static int hello = 100; int main(){ int *ptr = 0x8049578; printf("%d\n",*ptr); static int hello = 100; return 0; }不过讨厌的是又变了。。。。。。。这个(全局变量区?怎么叫来着?)地址分配很动态,不如栈的地址那么稳固。