内存布局(一)栈

1.内存布局

⦁    栈:维护函数调用时的上下文
⦁    堆:应用程序动态分配的内存区域
⦁    可执行文件映像:存储可执行文件在内存里的映像
⦁    动态链接库映射区:存储动态链接库在内存里的映像
⦁    保留区:禁止访问的内存区域
    

                               图:Linux进程地址空间布局(内核版本2.4.x)

2.栈 

栈保存了一个函数调用所需要维护的信息:
⦁    函数的返回地址和参数
⦁    临时变量:函数的非静态局部变量及编译器自动生成的其他临时变量
⦁    上下文:函数调用前后需要保持不变的寄存器
在i386中,函数的活动记录用ebp和esp这两个寄存器划定范围,esp寄存器始终指向栈的顶部,ebp寄存器指向了函数活动的一个固定位置。ebp可以用来定位函数活动记录中各个数据。
      

                                                   图: 活动记录

函数的开头:

push ebp 把ebp压入栈中(称为old ebp)
move ebp , esp ebp = esp (此时ebp指向栈顶)
[可选] sub esp , ××× 在栈上分配×××字节的临时空间
[可选] push ××× 保存名为×××的寄存器(可重复多个)

函数的结尾:

[可选] pop ××× 恢复的寄存器(可重复多个)
move esp , ebp  恢复esp同时回收局部变量空间
pop ebp 从栈中恢复保存ebp的值
ret 从栈中取得返回地址,并跳转到该位置

2.1调用惯例

    函数的调用方和被调用方对函数如何调用,应该有明确的约定,这样的约定称为调用惯例。
    ⦁    函数参数的传递顺序和方式
    ⦁    栈的维护方式
    ⦁    名字修饰的策略
    C语言中存在多个调用惯例,默认的是cdecl,cdecl的内容如表:

参数传递 从右至左的顺序将参数入栈
出栈方 函数调用方
名字修饰 在函数名称前加1个下划线

2.2 实例

void f(int x, int y)
{
    ...
    return ;
}

int main()
{
    f(1,3); 
    return 0;
}

    
                                           图: main函数的执行流程                

猜你喜欢

转载自blog.csdn.net/liyazhen2011/article/details/82318760
今日推荐