关键词:
目录
各种寄存器的作用
eax是“累加器”(accumulator),它是很多加法乘法指令的缺省寄存器
ebx是“基地址”(base)寄存器,在内存寻址时存放基地址
ecx是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
edx:总是被用来放整数除法产生的余数。
esp:寄存器存放当前线程的栈顶指针
ebp:寄存器存放当前线程的栈底指针
main()函数的调用
VS2013中mainCRTStartup()函数内部调用__tmainCRTStartup()函数,
__tmainCRTStartup()函数内部调用main()函数
通过汇编观察函数调用过程
int Add(int x, int y)
int z = 0;
z = x + y;
return z;
int main(void)
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d\\n", c);
return 0;
汇编代码
int main(void)
00301900 push ebp
00301901 mov ebp,esp
00301903 sub esp,0E4h
00301909 push ebx
0030190A push esi
0030190B push edi
0030190C lea edi,[ebp+FFFFFF1Ch]
00301912 mov ecx,39h
00301917 mov eax,0CCCCCCCCh
0030191C rep stos dword ptr es:[edi]
0030191E mov ecx,30C003h
00301923 call 0030132A
int a = 10;
00301928 mov dword ptr [ebp-8],0Ah
int b = 20;
0030192F mov dword ptr [ebp-14h],14h
int c = 0;
00301936 mov dword ptr [ebp-20h],0
c = Add(a, b);
0030193D mov eax,dword ptr [ebp-14h]
00301940 push eax
00301941 mov ecx,dword ptr [ebp-8]
00301944 push ecx
00301945 call 003010B9
0030194A add esp,8
0030194D mov dword ptr [ebp-20h],eax
printf("%d\\n", c);
00301950 mov eax,dword ptr [ebp-20h]
00301953 push eax
00301954 push 307B30h
00301959 call 003010D7
0030195E add esp,8
return 0;
00301961 xor eax,eax
上面提到main函数也是被调用的,所以当代码走到main函数中时,调用main函数的函数的栈帧已经被创建好了。
main()函数栈帧开辟过程
第3行把ebp压栈,第4行把esp的值赋给ebp,第5行esp减去0E4h,此时esp和ebp之间就是main函数的栈帧
6-8行把ebx、esi、edi压栈
lea表示load effective address加载有效地址
第9行到第12行将main函数栈帧的内容全部初始化位cccccccc
此时main函数栈帧开辟好了。
第16行将ebp-8的位置初始化为10,这是变量a的空间,18行将ebp-14h的位置赋值给20,为变量b,20行ebp-20h的位置赋值为0,为变量c
接下来第22行把ebp-14h的值(也就是b的20)赋给eax,并把eax压栈,把ebp-8的值(也就是a的10)赋给ecx,把ecx压栈。然后第26行call指令调用Add()函数,在调用call指令时会把call指令的下一条指令的地址压栈
Add()函数栈帧开辟过程
接下来调用Add()函数
Add()函数的汇编
int Add(int x, int y)
00301790 push ebp
00301791 mov ebp,esp
00301793 sub esp,0CCh
00301799 push ebx
0030179A push esi
0030179B push edi
0030179C lea edi,[ebp+FFFFFF34h]
003017A2 mov ecx,33h
003017A7 mov eax,0CCCCCCCCh
003017AC rep stos dword ptr es:[edi]
003017AE mov ecx,30C003h
003017B3 call 0030132A
int z = 0;
003017B8 mov dword ptr [ebp-8],0
z = x + y;
003017BF mov eax,dword ptr [ebp+8]
003017C2 add eax,dword ptr [ebp+0Ch]
003017C5 mov dword ptr [ebp-8],eax
return z;
003017C8 mov eax,dword ptr [ebp-8]
003017CB pop edi
003017CC pop esi
003017CD pop ebx
003017CE add esp,0CCh
003017D4 cmp ebp,esp
003017D6 call 0030124E
003017DB mov esp,ebp
003017DD pop ebp
003017DE ret
从第3行开始的一系列操作和上面的main函数中一样,依然是为函数开辟栈帧,并且把Add()函数栈帧空间初始化为cccccccc。
第16行把ebp-8的位置赋值为0,作为变量z的空间,18行把ebp+8位置的值放到eax中,19行把ebp+12的位置的值放到eax中,完成了两个变量的相加
第20行把eax中的30放到ebp-8也就是变量z的空间
return z,局部变量z在函数执行结束后销毁了,所以第22行的意思是把放在z变量中的两个数求和的结果保存在eax中。
Add()函数栈帧销毁过程
第24-26行把edi、esi、ebx出栈,然后把ebp赋给esp,pop掉ebp让ebp重新指向main函数栈底的位置,ret返回到之前保存的call指令的下一条指令的地址,自此Add函数调用结束,继续执行main函数
返回main函数后形参x和形参y没用了,把他们也出栈
过程如下:
回到main()函数后把eax中保存的30赋给ebp-20也就是c,此时完成了Add()函数栈帧的创建,传递形参,求值并保存在eax中,Add函数销毁,将函数返回值赋给变量c的一系列操作。
函数栈帧的创建和销毁(代码片段)
目录各种寄存器的作用main()函数的调用通过汇编观察函数调用过程main()函数栈帧开辟过程Add()函数栈帧开辟过程Add()函数栈帧销毁过程各种寄存器的作用eax是“累加器”(accumulator),它是很多加法乘法指令的缺省寄存器ebx是“... 查看详情
函数栈帧的创建与销毁(代码片段)
文章目录1.函数栈帧的概念2.函数栈帧的创建2.1main函数函数栈帧的创建过程2.2main函数中创建变量2.3Add函数函数栈帧的创建2.4Add函数栈帧的销毁1.函数栈帧的概念函数栈帧:使用每一个函数都要在栈区开辟一块空间.栈帧也叫过程活... 查看详情
函数栈帧的创建和销毁(代码片段)
...的说明二、对于创建和销毁的全过程1.对于_mainCRTstarup的函数的创建2.对于main函数的创建(1).为什么有时候会打印出烫烫烫3.对于Add的函数的创建(2).为什么说形参不在函数中(3).函数中return值如何放回的>(4).ebp-main出栈后ebp寄存器... 查看详情
函数栈帧的创建和销毁(待写)(代码片段)
函数栈帧的创建和销毁main函数被调用的过程:具体过程main函数被调用的过程:mainCRTStartup()调用_tmainCRTStartup()再调用main()寄存器:ebp(栈底指针),esp(栈顶指针)(sp是esp的低16位,esp是rsp的低32位,ss是16位堆栈... 查看详情
函数栈帧的创建与销毁(代码片段)
...什么是栈帧C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。首先应该明白,栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈... 查看详情
函数栈帧的创建与销毁(代码片段)
文章目录1.函数栈帧的概念2.函数栈帧的创建2.1main函数函数栈帧的创建过程2.2main函数中创建变量2.3Add函数函数栈帧的创建2.4Add函数栈帧的销毁1.函数栈帧的概念函数栈帧:使用每一个函数都要在栈区开辟一块空间.栈帧也叫过程活... 查看详情
图解函数栈帧-函数的创建与销毁(代码片段)
函数栈帧🎂前言🌹栈帧的概念💖准备工作😀main函数栈帧的创建及初始化😁main函数的被调用😂main函数栈帧的开辟🤣main函数栈帧的初始化👩临时变量的创建。👨Add函数栈帧的创建🧑Add... 查看详情
c语言深入逐汇编详解函数栈帧的创建和销毁过程(代码片段)
【C语言深入】逐汇编详解函数栈帧的创建和销毁过程一、图解大概过程二、函数栈帧的创建过程1、简介一些需要用到的汇编指令和寄存器2、调用main函数的函数3、局部变量的初始化4、形成临时拷贝5、函数调用6、形成栈帧7、提... 查看详情
函数栈帧的创建与销毁,带你了解代码底层原理(代码片段)
...么创建的?(2)为什么局部变量的值是随机的?(3)函数是怎么传参的?传参的顺序如何?(4)形参和实参是什么关系?(5)函数调用是怎么做的?(6)函数调用结束后是怎么返回的?这些疑问其实都和函数栈帧... 查看详情
内功修炼《函数栈帧的创建和销毁》建议收藏(代码片段)
...️⃣为什么未初始化的局部变量的值是随机值?3️⃣函数是如何传参的?以及传参的顺序是怎样的?4️⃣形参和实参是什么关系?5️⃣ 查看详情
c语言学习--函数栈帧的创建和销毁(代码片段)
...说局部变量未初始化时,其中存储的时随机值?函数到底时如何传参的?实参传递的顺序又是怎样的?形参和实参之间有着什么关系?函数调用结束后,结果是如何返回的?这些问题大 查看详情
函数栈帧的创建和销毁——“c”(代码片段)
...你们好呀,今天小雅兰来为大家介绍一个知识点——函数栈帧的创建和销毁。其实这个知识点,我们很早之前就要讲,但是因为我的一系列原因,才一直拖到了现在,那么,话不多说,让我们一起进入... 查看详情
图解c/c++语言底层:函数调用过程之函数栈帧的创建和销毁(上)(代码片段)
**文章目录函数栈帧的创建和销毁什么是寄存器?寄存器分类寄存器用途什么是"栈"?函数栈帧的概念函数压栈的过程示例代码和主函数汇编指令(部分)汇编指令:构建函数栈帧准备(一)汇编指令:构建函数栈... 查看详情
函数的调用过程,栈帧的创建和销毁。
一.函数调用1.函数调用过程涉及到的寄存器: (1)esp:栈指针寄存器(extendedstackpointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。 (2)ebp:基址指针寄存器(extendedbasepointer),其内存放着一个... 查看详情
c语言函数栈帧的创建和销毁,以简单函数的调用来进行详细刨析(代码片段)
1、为什么需要了解函数的栈帧大家对于程序很少有人会对底层的东西刨根问底,很多人写程序大多就是写出来能够成功运行起来就大无所措了,但是很少有人对程序是怎么跑起来较为关心,比如:局部变量是怎么... 查看详情
图解c/c++底层:函数栈帧的创建和销毁(下篇)
函数栈帧的创建和销毁(下篇)上篇原文链接根据上篇的函数栈帧过程的学习,我们了解到:什么是寄存器?计算机的速度最快的存储单元,因为寄存器是集成在CPU之上的,与内存是不同的独立的存储空间。什么... 查看详情
学好c语言,还需要掌握这个内功——函数栈帧的创建与销毁(代码片段)
...是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参的?传参的顺序是什么?形参和实参是什么关系?函数调用结束后怎么返回?看完这篇文章,一切将豁然开朗……预备知识在进入正题之... 查看详情
内功修炼《函数栈帧的创建和销毁》建议收藏(代码片段)
...️⃣为什么未初始化的局部变量的值是随机值?3️⃣函数是如何传参的?以及传参的顺序是怎样的?4️⃣形参和实参是什么关系?5️⃣函数调用是怎么做的?6️⃣函数调用结束后是怎么返回的?⚠这里... 查看详情