ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C语言的main函数反汇编笔记

2021-01-06 03:02:08  阅读:342  来源: 互联网

标签:esp edi mov C语言 eax ebp 反汇编 0C0h main


阅读本文需要一点汇编语言的基础知识

#include <stdio.h>

int main(void)
{
	return 0;
}

将这段C语言代码在VS2019下进行反汇编后:

#include <stdio.h>

int main(void)
{
008B4370  push        ebp  
008B4371  mov         ebp,esp  
008B4373  sub         esp,0C0h  
008B4379  push        ebx  
008B437A  push        esi  
008B437B  push        edi  
008B437C  lea         edi,[ebp-0C0h]  
008B4382  mov         ecx,30h  
008B4387  mov         eax,0CCCCCCCCh  
008B438C  rep stos    dword ptr es:[edi]  
008B438E  mov         ecx,offset _04D15DCE_C语言模板@c (08BC003h)  
008B4393  call        @__CheckForDebuggerJustMyCode@4 (08B1307h)  
	return 0;
008B4398  xor         eax,eax  
}
008B439A  pop         edi  
008B439B  pop         esi  
008B439C  pop         ebx  
008B439D  add         esp,0C0h  
008B43A3  cmp         ebp,esp  
008B43A5  call        __RTC_CheckEsp (08B1230h)  
008B43AA  mov         esp,ebp  
008B43AC  pop         ebp  
008B43AD  ret  

下面对这段汇编代码进行分析:

008B4370  push        ebp  
008B4371  mov         ebp,esp

这两段代码叫做函数序言,每次进入函数时都要写这两段代码。将ebp压入栈中是为了对函数在栈中的空间建立起始点,而将esp的地址复制给ebp则是让ebp指向栈顶(ebp在压入栈前指向的地址是未知的),并且ebp在整个函数的运行中地址都不会改变。而esp则相反,只要有变量或寄存器压入栈中其指向的地址值都会改变。

008B4373  sub         esp,0C0h

将esp的地址向下减少C0十进制的192),这是为了给函数中的局部变量提供空间(这部分空间也叫栈帧

008B4379  push        ebx  
008B437A  push        esi  
008B437B  push        edi  

将ebx,esi,edi压入栈中

008B437C  lea         edi,[ebp-0C0h]  
008B4382  mov         ecx,30h  
008B4387  mov         eax,0CCCCCCCCh  
008B438C  rep stos    dword ptr es:[edi]

edi指向[ebp-0C0h]地址所在的空间(这里为什么不是上面的esp-0C0h呢?因为esp的地址发生了改变,如果用esp的话函数在运行时可能会出错。0C0h十进制为192

ecx被赋值3010进制48,eax被赋值CCCCCCCC10进制3435973836

rep stos是一个循环语句,计数器由ecx负责,rep执行循环的条件是ecx不为0,且每进行一次循环ecx都会减1;stos意为将eax的内容填充edi所指向空间中,如果配合rep的话会根据系统的位数来确定地址的增长数(在32位系统中,地址的增长或减小单位都是4个字节,64位系统中为8个字节),从而做到对多个空间进行填充。

若将ebp的地址看做是0,会发现在循环结束后由最开始的那三段代码所分配的栈空间,刚好填充满。48 * 4 = 192

008B4398  xor         eax,eax

将eax归0,并将eax的值返回。main函数与一般的函数区别不是很大,基本上C语言函数在调用前一般都会将eax、ecx、edx这三个寄存器中的某一个压入栈中,这是是因为这三个寄存器由调用方保存,压栈的目的是防止值在调用函数后被修改。

008B439A  pop         edi  
008B439B  pop         esi  
008B439C  pop         ebx

栈是一种数据结构,遵循“先进后出”原则,由于这三个寄存器是最后入栈的那么理应最先出栈,且edi最先出栈。

008B439D  add         esp,0C0h  

esp地址+C0,将栈帧空间进行清除

008B43AA  mov         esp,ebp  
008B43AC  pop         ebp  
008B43AD  ret  

最后这三段代码叫做函数尾声,每个函数在结束后也都要写这三段代码。这里的esp指向ebp,并返回到函数调用处

标签:esp,edi,mov,C语言,eax,ebp,反汇编,0C0h,main
来源: https://www.cnblogs.com/ICeVe/p/14238890.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有