您的位置:首页 > 其它

栈结构 BP 进程虚拟地址空间

2011-09-29 20:22 344 查看
栈结构(参数入栈顺序跟调用方式有关,这里以C语言默认的CDECL为例(参数由右向左进入堆栈)):
| ....................| (栈底方向,高位地址)
| 参数3 |
| 参数2 |
| 参数1 |
| 返回地址 |
-| 上一层[EBP] |
| 局部变量2 |
| 局部变量1 |
|.....................| (栈顶方向,低位地址)

栈一直随着函数调用的深入,一直想栈顶方向压下去。每次调用函数时候,先压函数参数(从右往左顺序压),再压入函数调用下条指令的地址(由call完成)。接着进入调用函数体中先执行 pushq %rbp; movq %rsp, %rbp(一般已经由编译器加入到函数头中了),接着就是吧函数体中的局部变量压入栈中。再遇到函数的调用的嵌套则依此类推。(added by smsong)

pushq %rbp; movq %rsp, %rbp这两条指令实在大有深意:首先将rbp入栈,然后将栈顶指针rsp赋值给rbp。movq %rsp, %rbp这条指令表面上看是用rsp把原来rbp的值覆盖了,其实不然——因为给rbp赋值之前,原rbp值已被压栈(位于栈顶),而新的rbp又恰恰指向栈顶
此时rbp寄存器就已处于一个很重要的地位,该寄存器中存储着栈中的一个地址(原rbp入栈后的栈顶),从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,而该地址处又存储着上一层函数调用时的rbp值!

进程的虚拟地址空间

| ....................|

| ....................|

|内核虚拟存储器| (高位地址)

|用户栈(运行时创建)|

|共享库的存储器的映射区域|

|运行时堆|

|读/写数据|

|只读的代码和数据|

|未用| (低位地址)

| ....................|

| ....................|
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: