Go最全《伏C录》凝丹篇-函数栈帧理解手册_栈枝1(3),字节跳动厂内部超高质量Flutter+Kotlin笔记

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

指令分说:

int main()
{
00F71E40  push        ebp  
00F71E41  mov         ebp,esp  
00F71E43  sub         esp,0E4h  

以上图为参照。

第一条指令:将寄存器ebp的值压栈

第二条指令:将寄存器esp的值赋值给ebp

第三条指令:将esp-0E4h赋值给寄存器esp,形象的表述是esp向低地址方向移动4个字节,上端为低地址,下端为高地址,即向上移动4字节空间。

栈区视图变为:

这三条指令,简单来说就是为main函数在栈区开辟了一块空间(这块空间大小系统会帮我们自动开辟好。)

指令分说:

00F71E49  push        ebx  
00F71E4A  push        esi  
00F71E4B  push        edi  

将三个寄存器的值压入栈中

栈区视图变为:

指令分说:

00F71E4C  lea         edi,[ebp-24h]  
00F71E4F  mov         ecx,9  
00F71E54  mov         eax,0CCCCCCCCh  
00F71E59  rep stos    dword ptr es:[edi] 

这四条指令我们就解读了,效果就是将main函数的栈帧空间以16进制值cccccccc填充。

栈区视图变为:

指令分说:

00F71E5B  mov         ecx,0F7C003h  
00F71E60  call        00F7130C 

这两条指令是编译器检查用的,初学不必花费更多时间了解更细节的部分。

vs2013没有这一检查部分,vs2019检查很严格。

指令分说:

int a = 10;
00F71E65  mov         dword ptr [ebp-8],0Ah  
	int b = 20;
00F71E6C  mov         dword ptr [ebp-14h],14h  
	int z = 0;
00F71E73  mov         dword ptr [ebp-20h],0  

第一条汇编指令:将0Ah放入[ ebp-8 ]这块空间中,即把a放入那块空间。

第二条汇编指令:将14h放入[ ebp-14h ]这块空间中,即把b放入那块空间中。

第三条汇编指令:将0放入[ ebp-20h ]这块空间中。即把z放入那块空间中。

栈区图示:

简单来说:就是将局部变量放入对应的函数栈帧中。

指令分说:

z = Add(a, b);
00F71E7A  mov         eax,dword ptr [ebp-14h]  
00F71E7D  push        eax  
00F71E7E  mov         ecx,dword ptr [ebp-8]  
00F71E81  push        ecx  

第一条指令:将【ebp-20】这块空间4字节的数据放入eax中。即把b=20的数据放入eax中。

第二条指令:将eax的数据压栈。

第三条指令:将【ebp-8】这块空间4字节的数据放入ecx中。即把a=10的数据放入ecx中。

第四条指令:将ecx的数据压栈。

栈区视图:

这里的20和10,就是我们传过去的实参,之后Add函数调用的x和y就是指这两块空间。

那么我们可以知道:函数传参是从右向左传的。这里就是先传的b再传的a。

指令分说:

00F71E82  call        00F710B4 

调用的函数:
int Add(int x, int y)
{
00F71740  push        ebp  
00F71741  mov         ebp,esp  
00F71743  sub         esp,0CCh  
00F71749  push        ebx  
00F7174A  push        esi  
00F7174B  push        edi  
00F7174C  lea         edi,[ebp-0Ch]  
00F7174F  mov         ecx,3  
00F71754  mov         eax,0CCCCCCCCh  
00F71759  rep stos    dword ptr es:[edi]  
00F7175B  mov         ecx,0F7C003h  
00F71760  call        00F7130C  
	int z = x + y;
00F71765  mov         eax,dword ptr [ebp+8]  
00F71768  add         eax,dword ptr [ebp+0Ch]  
00F7176B  mov         dword ptr [ebp-8],eax  
	return z;
00F7176E  mov         eax,dword ptr [ebp-8]  
}
00F71771  pop         edi  
00F71772  pop         esi  
00F71773  pop         ebx  
00F71774  add         esp,0CCh  
00F7177A  cmp         ebp,esp  
00F7177C  call        00F71235  
00F71781  mov         esp,ebp  
00F71783  pop         ebp  
00F71784  ret  

第一条汇编指令:call是调用指令,调用Add函数。

经过上次的指令,这里我就直接介绍效果了。

00F71740  push        ebp  
00F71741  mov         ebp,esp  
00F71743  sub         esp,0CCh  

这三条指令,为Add函数在栈区开辟对应的空间大小。

栈区图示:

00F71749  push        ebx  
00F7174A  push        esi  
00F7174B  push        edi  

将ebx,esi,edi入栈。

图示:

00F7174C  lea         edi,[ebp-0Ch]  
00F7174F  mov         ecx,3  
00F71754  mov         eax,0CCCCCCCCh  
00F71759  rep stos    dword ptr es:[edi]  

对Add函数栈帧做初始化,将里面的数据置换为cccccccc。(用于初始化栈帧的具体数值取决于编译器)

00F7175B  mov         ecx,0F7C003h  
00F71760  call        00F7130C  

编译器做的检查,不必理会。

int z = x + y;
00F71765  mov         eax,dword ptr [ebp+8]  
00F71768  add         eax,dword ptr [ebp+0Ch]  
00F7176B  mov         dword ptr [ebp-8],eax  

取[ebp+8]空间的数据放入eax中

取 [ebp+0Ch]  与eax的数据相加后放入eax中。

将eax的值放入ptr [ebp-8]中。

图示:

 return z;
00F7176E  mov         eax,dword ptr [ebp-8]  

返回时,通过寄存器的方式,将返回值交给寄存器。

00F71771  pop         edi  
00F71772  pop         esi  
00F71773  pop         ebx  
00F71774  add         esp,0CCh  
00F7177A  cmp         ebp,esp  
00F7177C  call        00F71235  
00F71781  mov         esp,ebp  
00F71783  pop         ebp  
00F71784  ret  

代码分说:

00F71771  pop         edi  
00F71772  pop         esi  
00F71773  pop         ebx  

将edi、esi、ebx出栈

图示

00F71774  add         esp,0CCh 

00F7177A  cmp         ebp,esp  
00F7177C  call        00F71235  
00F71781  mov         esp,ebp  
00F71783  pop         ebp  

0CCh是Add函数栈帧的大小

所以esp向下移动到dbp的位置。

之后pop ebp,由于栈顶指向的是main函数栈帧的栈底,因此出栈ebp指向main函数栈帧的栈底。

图示:

调用Add返回之后,继续执行以下指令。

00A717F7  add         esp,8  
00A717FA  mov         dword ptr [ebp-20h],eax  
	return 0;

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

esp,8

00A717FA mov dword ptr [ebp-20h],eax
return 0;

[外链图片转存中…(img-zkUIo24B-1715820686411)]
[外链图片转存中…(img-7q2kXCsK-1715820686411)]
[外链图片转存中…(img-skoLvYvP-1715820686412)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值