服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言堆栈帧的介绍与创建

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

2021-12-09 14:21从善若水 C/C++

这篇文章主要给大家介绍了关于C语言堆栈帧的相关资料,堆栈帧 (stack frame)( 或活动记录 (activation Tecord)) 是一块堆栈保留区域,用于存放被传递的实际参数、子程序的返回值、局部变量以及被保存的寄存器,需要的朋友可以参考下

什么是堆栈帧?

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

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

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

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

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

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

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

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

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

我们来看一段code

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#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 
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//我们的汇编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语言堆栈帧内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_31985307/article/details/119302095

延伸 · 阅读

精彩推荐
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16