C语言堆栈帧的介绍与创建

 更新时间:2021年08月02日 11:47:00   作者:从善若水  
这篇文章主要给大家介绍了关于C语言堆栈帧的相关资料,堆栈帧 (stack frame)( 或活动记录 (activation Tecord)) 是一块堆栈保留区域,用于存放被传递的实际参数、子程序的返回值、局部变量以及被保存的寄存器,需要的朋友可以参考下

什么是堆栈帧?

       堆栈帧(stack frame)是一块堆栈保留区域,用于存放被传递的实际参数,子程序的返回值、局部变量以及被保存的寄存器。

堆栈帧的创建方法🐱‍👤【32bit Windows】

       (1)被传递的实际参数。如果有,则压入堆栈;

       (2)当子程序被调用时,使该子程序的返回值压入堆栈。如果使用寄存器保存返回值,则跳过此步;

       (3)子过程返回地址入栈;

       (4)子程序开始执行时,EBP被压入堆栈;

       (5)设置EBP等于ESP。从现在开始,EBP就变成了该子程序所有参数的引用基址;

       (6)如果有局部变量,修改ESP以便在堆栈中为这些变量预留空间;

       (7)如果需要保存寄存器,则将它们入栈;

我们来看一段code👇

#include<stdio.h>

int print_string(const char * str)
{
	/* EBP被压入堆栈,对应上述步骤(4) */
	//00FE18A0  push        ebp  

	/* 设置EBP等于ESP,对应上述步骤(5) */
	//00FE18A1  mov         ebp,esp  

	/* 虽然我们没有局部变量,但是编译器还是预留了空间,对应上述步骤(6) */
	//00FE18A3  sub         esp,0C0h  

	/* 保存寄存器,对应上述步骤(7) */
	//00FE18A9  push        ebx  
	//00FE18AA  push        esi  
	//00FE18AB  push        edi  
 
    printf("%s\n", str);
    /* 将printf函数的入参压入堆栈 */
	//00FE18C1  mov         eax,dword ptr [str]  
	//00FE18C4  push        eax  
	//00FE18C5  push        offset string "%s\n" (0FE7B30h)  
	//00FE18CA  call        _printf (0FE10CDh)  
	//00FE18CF  add         esp,8  
    
    return 1;
	/* 使用寄存器存储返回值 */
	//00FE18D2  mov         eax,1  
}

int main()
{
    char* str = "Hello World";
    /* 将"Hello World"的地址存在str变量中 */
	//00FE1865  mov         dword ptr [str],offset string "Hello World" (0FE7B34h)  
    print_string(str);
    /* 将str 中的值存在eax寄存器中 */
	//00FE186C  mov         eax,dword ptr [str]  
	
	/* eax压栈,对应上述步骤(1) */
	//00FE186F  push        eax 
	
	/* 这里我们使用寄存器存储返回值,所以没有步骤(2) */
	/* call指令会自动将返回地址压栈,对应上述步骤(3) */
	//00FE1870  call        _print_string (0FE13B1h)
	
	/* 清空 print_string函数的入参空间 */  
	//00FE1875  add         esp,4  

    return 0;
	//00FE1878  xor         eax,eax  
}

我们再通过一张图来解释一下:

//我们的汇编code如下
print_string PROC
	push ebp        // 保存基址寄存器
	mov ebp,esp     // 堆栈帧基址
	push ecx
	push edx        // 保存寄存器
	mov eac,[ebx+8] // 取堆栈参数
	.
	.
	pop edx         // 恢复被保存的寄存器
	pop ecx
	pop ebp         // 恢复基址指针
	ret             // 清除堆栈
print_string ENDP

函数print_string() 对应的堆栈帧如下图👇

总结

到此这篇关于C语言堆栈帧的文章就介绍到这了,更多相关C语言堆栈帧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++基于easyx图形库实现打砖块游戏

    C++基于easyx图形库实现打砖块游戏

    这篇文章主要为大家详细介绍了C++基于easyx图形库实现打砖块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • C++二分查找算法实例

    C++二分查找算法实例

    这篇文章主要为大家详细介绍了C++二分查找算法的实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 获取一个文件行数的方法

    获取一个文件行数的方法

    获取一个文件行数的方法,需要的朋友可以参考一下
    2013-03-03
  • C++实现简单迷宫游戏

    C++实现简单迷宫游戏

    这篇文章主要为大家详细介绍了C++实现简单迷宫游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • 标准C++类string的Copy-On-Write技术

    标准C++类string的Copy-On-Write技术

    这里,我想从C++类或是设计模式的角度为各位揭开Copy-On-Write技术在string中实现的面纱,以供各位在用C++进行类库设计时做一点参考
    2013-11-11
  • C语言实现学生个人消费管理系统

    C语言实现学生个人消费管理系统

    这篇文章主要为大家详细介绍了C语言学生个人消费管理系统开发,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言实现单词小助手改进版

    C语言实现单词小助手改进版

    这篇文章主要为大家详细介绍了C语言实现单词小助手的改进版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • C语言开源库iniparser解析ini文件的方法

    C语言开源库iniparser解析ini文件的方法

    INI(Initialization File)文件是一种简单直观的数据存储格式,常用于配置应用程序的初始化设置,使用 iniparser 库的应用程序可以很方便地读取和解析INI文件中的配置信息,大大简化了对配置文件的处理工作,降低了程序的开发复杂度,感兴趣的的朋友跟随小编一起看看吧
    2024-04-04
  • C语言关于include顺序不同导致编译结果不同的问题

    C语言关于include顺序不同导致编译结果不同的问题

    这篇文章主要介绍了在日常调试C语言中include的顺序不同从而影响最后编译结果不同的问题,究其原因是写代码的习惯所导致,下面跟小编一起来看看吧
    2022-04-04
  • VSCode远程代码开发及DNS隧道端口转发实现远程办公代码

    VSCode远程代码开发及DNS隧道端口转发实现远程办公代码

    这篇文章主要介绍了VSCode远程代码开发及DNS隧道端口转发实现远程办公,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04

最新评论