理解栈与帧指针:函数参数、局部变量与帧指针地址分布疑问
帧指针两侧分布参数与局部变量的原理
你观察到的现象是32位x86架构下传统带帧指针的栈帧布局的标准表现,帧指针(对应ebp寄存器)本身就是栈帧的分界点,而非指向栈帧的某一端,具体栈帧构建逻辑如下:
- 调用
myfunction(4)前,main函数按照C调用约定(cdecl)先将参数4从右到左压入栈,此时栈顶地址就是参数counter的地址,即你观测到的0xbffff610 - 执行
call指令触发函数调用时,CPU自动将返回地址(call指令下一条指令的地址)压入栈,栈顶指针esp向下(地址减小方向)偏移4字节 - 进入
myfunction后首先执行函数序言指令:- 第一步执行
push %ebp,将main函数的旧帧指针压入栈,esp再减4 - 第二步执行
mov %esp, %ebp,将当前esp的值赋值给ebp,这就是你通过__builtin_frame_address(0)拿到的帧指针地址0xbffff608,该地址存储的内容就是main函数的旧帧指针
- 第一步执行
- 最后执行
sub $xxx, %esp分配局部变量空间,栈继续向下增长,因此所有局部变量都会分配在地址比ebp更低的区域,你观测到的局部变量result地址0xbffff5f8刚好对应ebp-0x10的位置
综上,32位x86标准栈帧布局中,ebp的分界属性是固定的:
- 地址高于ebp的区域(ebp正偏移):存储调用方传入的参数、函数返回地址
- 地址低于ebp的区域(ebp负偏移):存储当前函数的局部变量、需要被保存的被调用方保护寄存器值
这种布局的好处是不管栈顶esp怎么动态变化,都可以通过ebp的固定偏移快速访问参数和局部变量。
内容的提问来源于stack exchange,提问作者techhighlands
相关产品推荐
相关产品推荐

