c语言局部变量压栈顺序,C 程序局部变量压栈出栈的理解
写这篇总结的缘由仅仅出于巧合,五一前帮一位同学看51的程序,在查看汇编代码的时候(事实上我当时的汇编知识基本都还给了老师),无意中问起我“某个局部变量的声明怎么没有对应的汇编语句”,我没有答出来。当时也只是把它当做一种常识给记了下来,平时不论还是在DSP、16位的单片上还是PC平台上编写c程序,由于程序不是很复杂且芯片资源通常足够,因此很少会考虑内存分配、堆栈方面的内容。这几天在看《Linux c 一站式编程》这本书关于变量内容的时候突然想起这个问题,顿时觉得很有必要把深究一下。
因为网络账号还没充钱的缘故,ubuntu系统还不能及时升级,因此在VC平台下做了以下相关试验。代码如下:
int main(void)
{
int d;
int f = d+1;
d = 1;
d = hello(5,10);
return 0;
}
对应的汇编代码如下:
16: int main(void)
17: {
00410960 push ebp
00410961 mov ebp,esp
00410963 sub esp,48h
00410966 push ebx
00410967 push esi
00410968 push edi
00410969 lea edi,[ebp-48h]
0041096C mov ecx,12h
00410971 mov eax,0CCCCCCCCh
00410976 rep stos dword ptr [edi]
18:
19:
20: int d;
21: int f = d+1;
00410978 mov eax,dword ptr [ebp-4]
0041097B add eax,1
0041097E mov dword ptr [ebp-8],eax
22: d = 1;
00410981 mov dword ptr [ebp-4],1
23: //printf('Hello world!\n');
24: //printf("a = %f,b=%f,c=%f",a,b,c);
25: //getch();
26: d = hello(5,10);
00410988 push 0Ah
0041098A push 5
0041098C call @ILT+5(_hello) (0040100a)
00410991 add esp,8
00410994 mov dword ptr [ebp-4],eax
27: return 0;
00410997 xor eax,eax
28: }
从以上汇编代码20、21两行中可以看到“int d”语句确实没有对应的函数声明。但是在用d给f赋值的时候,d却对应了dword ptr [ebp-4],这一点刚开始的时候很是疑惑,后来在看过几篇相关文章后得知,局部变量的声明和释放是由编译器调整栈指针(Stack Pointer)位置来完成的[1],编译器首先根据变量的类型和数量计算存储局部变量所需的空间,然后调整ESP的值来为局部变量分配空间。“int d;” 在编译的时候应该是将变量d 与地址 dword prt[ebp-4]对应了起来,既d的内存地址为ebp-4到ebp-7;同理,f值往上调整,对应ebp-8到ebp-11。
然而,了解了以上内容还远不够理解函数压栈出栈的原理,于是对main函数下面对应的17行做了分析,考虑linux平台下的情况[],主要针对ESP和EBP两个栈寄存器作分析解释。以下是通过单步调试的方式得到的结果:
图1 未单步前
未运行单步执行前,程序和寄存器值如图1所示。ESP = 0012FF84 ,EBP = 0012FFC0;这是旧的(在函数调用时就是主调函数的)栈对应的空间。
图2 执行 “00410960 push ebp”
执行的“push ebp”后,程序和寄存器值如图2所示。ESP = 0012FF80,EBP = 0012FFC0;因为是要在原来栈的基础上开辟新的栈空间,因此,在旧栈(不知道该如何称呼,暂且这么认为)的栈顶上移了四个字节作为新栈的栈底。因此ESP由原来的0012FF84变为0012FF80 。
图3 执行 “00410961 mov ebp,esp”
“mov ebp,esp”是为了将新的栈底指针赋值为ebp,如图3所示。ESP = 0012FF80,EBP = 0012FF80 。
图4 执行 “00410963 sub esp,48h”
“ sub esp,48h”则是为了给局部变量在栈中分配一定的存储空间,如图4所示。ESP由原来的0012FF80减小到0012FF38,这里需要注意的是0012FF80到0012FF7C为旧栈中的栈顶对应的四个字节,因此局部变量的分布实际是从地址0012FF7C到地址0012FF34共72个字节空间。
图5 执行 “push ebx ;push esi;push edi”
接下来,连续执行三个push,将相应的寄存器值压栈。
时间限制,下面转写了参考中的文献以备忘。
“
1.在一个栈中,依据函数调用关系,发起调用的函数(caller)的栈帧在下面(高地址方向),被调用的函数的栈帧在上面。
2.每发生一次函数调用,便产生一个新的栈帧,当一个函数返回时,这个函数所对应的栈帧被清除(eliminated)
”[1]
c语言局部变量压栈顺序,C 程序局部变量压栈出栈的理解相关推荐
- 元素入栈顺序确定,共有多少种出栈顺序?----Python
文章目录 问题描述 对栈的理解 题目的思考 python代码 卡特兰数 扩展思路 问题描述 前几天看到一个题目,假设五个元素的入栈顺序为e1.e2.e3.e4.e5,那么共有多少种出栈顺序?一时之间思 ...
- 出栈(释放栈)和引用栈内数据意义不等同,和嵌套有关系但不是等同关系,局部变量进栈操作,不是局部变量自动带有进栈指令。汇编语言后局部变量操作是包含进栈操作指令PUSH和栈内地址存储数据调用,出栈。
出栈(释放栈)和引用栈内数据意义不等同,和嵌套有关系但不是等同关系,局部变量进栈操作,不是局部变量自动带有进栈指令.汇编语言后局部变量操作是包含进栈操作指令PUSH和栈内地址存储数据调用,出栈. 2. ...
- PAT甲级1051 Pop Sequence:[C++题解]模拟栈、判断序列是否是合法的出栈序列
文章目录 题目分析 题目来源 题目分析 来源:acwing 分析: 题意:将1~N压栈,判断给定序列是否是合法的出栈序列. 对于序列1~N中的每个值i,先将其压入栈.然后对于它就有两种处理方法:要么压 ...
- 理解——先序遍历是入栈过程,中序遍历是出栈过程
遇到这样一道题:先序序列为a,b,c,d的不同二叉树的个数是多少? 拿到这个问题 首先,要了解到先序遍历和中序遍历都是需要用到栈,其中,先序遍历是入栈过程,中序遍历是出栈过程 然后,二叉树的先序序列和 ...
- 全栈路线_程序员该走全栈路线还是深度专家路线?
程序员该走全栈路线,还是深度路线?相信这个问题是所有程序员都会思考的一个问题. 先说说何谓全栈?全栈工程师,英文Full Stack engineer,一般是指能独立完成产品开发的人,同时具备前端和后 ...
- 问题-栈S最多能容纳4个元素,现有6个元素按A、B、C、D、E、F顺序进栈,问可能的出栈顺序。...
住栈的特性:对于取出栈内元素每次只能从栈顶开始取(后进先出(栈满时,只能先出后进)) 由于栈内只能容纳4个元素: 所以 E F不可能第一个出栈: 当栈内少于四个元素时 既可以选择进栈,也可以选择出栈 ...
- PTA 栈 (20分)(全网首发)(实现一个栈Stack,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1))
题目描述: 我们知道平凡的栈有几个操作: push(value) 将 value 压入栈 pop() 将栈顶元素弹出, 并返回这个弹出的元素. 现在我们想要在平凡栈的基础上实现以下几个操作: push ...
- 栈顶指针不同进行“进、出”栈的易错题
1.若一个栈元素用数组data[1..n]存储,初始栈顶指针top为n,则以下元素x进栈最适合的操作是______. A.top++; data[top]=x; B.data[top]=x; top+ ...
- 判断出栈顺序是否正确
先说一下题目: 假设有一个栈S,每次我们可以把序列A(含N个元素)中的第一个元素移入栈S,也可以是从栈顶弹出一个元素放入出栈序列B.这 样,经过N次入栈和出栈操作后,我们可以得到一个出栈序列B. 现在 ...
最新文章
- Hotpatch潜在的安全风险
- 数学题 贪心+二分答案
- 模板库 | 销售管理类报表,邀您提反馈
- 传统到敏捷的转型中,谁更适合做Scrum Master?
- linux系统找运行指令,Linux系统常用指令总结
- 技术面试别扯智力题!
- Maven的配置和使用(三)
- Photoshop数位板无压感解决方法
- AgileEAS.NET SOA 中间件/敏捷软件开发平台
- 打开本地flash webview open swf
- 微缩脚步趋缓 摩尔定律由于EUV微影技术延迟失去动力
- Axure 8 网页滚动效果+APP上下垂直拖动效果
- 登录界面---油管大佬
- 本周大新闻|CES 2023 AR/VR最全汇总
- 局域网(LAN)端口与广域网(WAN/外网)端口映射——实现让局域网机器在外网做服务器...
- IIS 服务器常见漏洞
- php点击切换图片的底部导航,如何优雅地使用BottomNavigationView实现底部导航栏+fragment切换效果...
- Linux Shell相关记笔记
- 时域同步平均TSA-学习笔记
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(3)- Serial Downloader模式(sdphost/MfgTool)...
热门文章
- Linux-epoll机制
- 护照读取_如何使用Android读取护照
- javascript通过console.log()控制台输出各种字体样式(3D文字、彩色背景色体)
- JS 实现红包雨效果,倒计时开红包 兼容移动端
- SDCC 2016架构运维峰会(成都站),讲师议题抢先看!
- 有这么一种茶几,它带着触摸屏!
- 语义鸿沟、异构鸿沟、数据缺失,多模态技术如何跨过这些坎?
- LabVIEW通过NI OPC实现与三菱FX 5U系列PLC的通讯
- 张蕾:2019年的机会在哪里?我看好这5个领域!
- 计算机信息技术导论课程总结,信息技术导论结课报告.docx