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

什么是堆栈帧?

堆栈帧(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 PROCpush ebp        // 保存基址寄存器mov ebp,esp     // 堆栈帧基址push ecxpush edx        // 保存寄存器mov eac,[ebx+8] // 取堆栈参数..pop edx         // 恢复被保存的寄存器pop ecxpop ebp         // 恢复基址指针ret             // 清除堆栈print_string ENDP

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

总结

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

也就越容易失败,还不如怀揣一颗平常心,

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

相关文章:

你感兴趣的文章:

标签云: