关键词:
C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。
首先,栈是从高地址向低地址延伸的。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。
先来看一个代码
#include <stdio.h>
void fun()
int tmp = 10;
int*p = (int*)(*(&tmp + 1));
*(p - 1) = 20;
int main()
int a = 0;
fun();
printf("a = %d\\n", a);
return 0;
这个代码输出的a的值时多少呢? 答案是20。
调用fun()函数后居然把a的值改掉了,从上面的代码可以看到并没有给fun()函数传a的地址,那么fun()函数为什么会把a的值改掉呢? 回答这个问题之前我们需要了解C语言函数的调用过程。
为了更好的观察到上述函数的调用过程,我们在VC 6.0环境下查看一下它的汇编代码。
在这之前首先要知道:
寄存器ebp称为“基址指针”,在未受改变之前始终指向栈底,用途是:在堆栈中寻址。
寄存器esp称为“栈指针”,会随着数据的入栈出栈移动,也就是说始终指向栈 顶。
函数调用过程如下图所示:
图中有部分esp移动的过程没有画出,但最终不管如何入栈出栈esp会在销毁空间后指向创建空间前esp最后指向的位置
从上面的汇编代码,我们可以看到fun()函数是通过找到变量a所在的栈的栈底地址,进而找到a的地
址,将a的内容改掉,这就解释了为什么没有给fun()传a的地址,却可以改变a的值。
总结:
函数在调用另一个函数之前会保存两个信息(1)函数调用完返回之后下一条指令的地址
(2)该函数的栈底的地址
最后分享一个使用ebp修改程序执行顺序的代码,并且最后esp回到原处,貌似什么都没发生的样子。
但是却在屏幕上多输出了一个funtest
#include <stdio.h>
void*p =NULL;
void*q =NULL;
void funtest()
int tmp =0;
int tmp2 =1;
printf("funtest\\n");
*(int*)(&tmp+2) =p;
void swap(int *pa, int *pb)
int tmp=0;
p= *(&tmp+2);
q= &tmp+2;
*(&tmp+2) = &funtest;
tmp = *pa;
*pa = *pb;
*pb = tmp;
int main()
int a =10;
int b =20;
swap(&a,&b);
printf("main\\n");
_asm
sub esp,4
return 0;
本文出自 “牛丽” 博客,请务必保留此出处http://15129279495.blog.51cto.com/10845420/1735749
函数栈帧的创建与销毁(代码片段)
文章目录1.函数栈帧的概念2.函数栈帧的创建2.1main函数函数栈帧的创建过程2.2main函数中创建变量2.3Add函数函数栈帧的创建2.4Add函数栈帧的销毁1.函数栈帧的概念函数栈帧:使用每一个函数都要在栈区开辟一块空间.栈帧也叫过程活... 查看详情
函数栈帧的创建与销毁(代码片段)
栈帧的创建与销毁什么是栈帧C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一... 查看详情
图解函数栈帧-函数的创建与销毁(代码片段)
函数栈帧🎂前言🌹栈帧的概念💖准备工作😀main函数栈帧的创建及初始化😁main函数的被调用😂main函数栈帧的开辟🤣main函数栈帧的初始化👩临时变量的创建。👨Add函数栈帧的创建🧑Add... 查看详情
《逆向工程核心原理》读书笔记——第7章栈帧(代码片段)
第7章栈帧7.1栈帧7.2调试示例:stackframe.exe7.2.1StackFrame.cpp7.2.2开始执行main()函数&生成栈帧7.2.3设置局部变量7.2.4add()函数参数传递与调用7.2.5开始执行add()函数&生成栈帧7.2.6设置add()函数的局部变量(x,y)7.2.7ADD运算7.2.8删除函数add()... 查看详情
juc并发编程线程运行原理--栈帧&栈帧图解(代码片段)
1.线程(栈)运行原理栈与栈帧:JavaVirtualMachineStacks(Java虚拟机栈)我们都知道JVM中由堆、栈、方法区所组成,其中栈内存是给谁用的呢?其实就是线程,每个线程启动后,虚拟机就会为其分配一块栈内存。每... 查看详情
浅谈函数栈帧(代码片段)
...上传码云,推荐关注哦~笔芯~ 目录 内存管理和函数栈帧一些准备工作main函数栈帧push压栈操作什么是压栈?出栈?ebp和espmain函数空间的开辟变量的创建以及传参创建变量传参(形式 查看详情
函数栈帧的创建与销毁(代码片段)
目录写在前面函数栈帧的创建与销毁了解两个寄存器ebp和esp函数栈帧创建与销毁的具体过程main函数的函数栈帧变量的创建Add函数栈帧的创建与销毁回到main函数总结写在前面在我们前期的学习编程的过程中,我们会遇到许多... 查看详情
函数栈帧的创建和销毁(代码片段)
...作用main()函数的调用通过汇编观察函数调用过程main()函数栈帧开辟过程Add()函数栈帧开辟过程Add()函数栈帧销毁过程各种寄存器的作用eax是“累加器”(accumulator),它是很多加法乘法指令的缺省寄存器ebx是“基地址”(base)寄存... 查看详情
递归&栈帧空间(代码片段)
递归函数:自己调用自己的函数1defdigui(n):2print(n)3ifn>0:4digui(n-1)5print(n)67digui(5)执行结果:152433425160708192103114125执行过程:1"""23代码从上到下执行:4digui(5)5print56digui(4)7print48digui(3)9print310digui(2)11print212digu 查看详情
函数栈帧的创建与销毁(代码片段)
文章目录1.函数栈帧的概念2.函数栈帧的创建2.1main函数函数栈帧的创建过程2.2main函数中创建变量2.3Add函数函数栈帧的创建2.4Add函数栈帧的销毁1.函数栈帧的概念函数栈帧:使用每一个函数都要在栈区开辟一块空间.栈帧也叫过程活... 查看详情
函数栈帧详解(代码片段)
在了解函数栈帧之前先要了解一些基础概念:首先是程序在编译阶段发生的处理参考一下博客:程序环境和预处理总结一下就是编译过程的最终产品是可执行程序——由一组机器语言指令组成。运行程序时,操作系统... 查看详情
函数栈帧详解(代码片段)
在了解函数栈帧之前先要了解一些基础概念:首先是程序在编译阶段发生的处理参考一下博客:程序环境和预处理总结一下就是编译过程的最终产品是可执行程序——由一组机器语言指令组成。运行程序时,操作系统... 查看详情
超详细函数栈帧(利用反汇编窥探底层原理)+建议收藏(代码片段)
...寄存器主函数是被谁调用的?调用逻辑是什么主函数栈帧的创建栈顶指针,栈底指针函数栈帧创建的预备工作Add函数是怎么被调用的前言学习函数栈帧之前我们得了解一下什么是寄存器,因为关于函数栈帧的知识是需... 查看详情
c语言进阶顶级神功!函数栈帧的创建和销毁(代码片段)
...文开始1.大致轮廓了解(源代码及反汇编)2.函数栈帧的创建和销毁总流程3.函数栈帧的创建3.1main函数的创建(分解)3.2Add函数的创建(分解)4.函数栈帧的销毁4.1main函数的销毁(分解)5.1Add函数的... 查看详情
c语言的函数栈帧究竟是什么?你知道吗?(代码片段)
内容导读1.寄存器2.函数栈帧2.1函数栈帧的概述2.2函数栈帧创建过程2.2.1被调用的main函数2.2.2函数栈帧创建与销毁的过程前面的话:作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!博主的... 查看详情
jvm理论:(三/3)运行时栈帧结构基于栈的字节码解释执行过程(代码片段)
一、栈帧结构 讲栈帧结构有必要回顾一下前文Class文件中的Code属性结构,如下图。 栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机栈的栈元素。每一个方法从调用开始到执行完成,都对应着... 查看详情
函数栈帧的创建和销毁(待写)(代码片段)
函数栈帧的创建和销毁main函数被调用的过程:具体过程main函数被调用的过程:mainCRTStartup()调用_tmainCRTStartup()再调用main()寄存器:ebp(栈底指针),esp(栈顶指针)(sp是esp的低16位,esp是rsp的低32位,ss是16位堆栈... 查看详情
栈帧(代码片段)
C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。首先,栈是从高地址向低地址延伸的。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶... 查看详情