文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>VC环境下对函数调用的汇编分析【原创】

VC环境下对函数调用的汇编分析【原创】

时间:2007-03-06  来源:loughsky

前沿:对于我们平常编程中常出现一些细节,如__stdcall和__cdecl编译器如何为我们处理,函数中变量以及new出来的变量到底存放于哪些地方,等等一些列问题。本文将和大家一起分析程序执行的汇编语言,通过对此过程掌握使自己在开发中熟悉并优化自己的代码。作者:天衣有缝,联系邮件:[email protected],MSN:[email protected],我的QQ群3226292,转载请保留完整文档。
 
1.环境:我使用的开发环境是vc7.1,其release单步调试需要对项目属性作如下修改:
“C++”--》“常规”--》“调试信息格式”  改为:“用于“编辑并继续”的程序数据库(/ZI)”
“C++”--》“优化”--》“优化”          改为:禁用(/Od)
如果你是vc6环境,可如下修改release版属性:
选中Win32 Release然后
Project-》setting-》C/C++ -》Category-》General
-》Optimization-》Disable(Debug)
-》Debug Info-》Program DataBase
-》Link---》Generate Debug Info打上钩

 
2.c语言代码,如下:
/***开始*****************************************************/
#include "stdafx.h"
int __cdecl add(int a, int b)
{
 int c;
 c = a + b;
 return c;
}

int _tmain(int argc, _TCHAR* argv[])
{
 int iResult = add(123, 456);
 printf(" ************ ");

 
 return 0;
}

/***结束*****************************************************/
 

3.程序分析过程,F10单步启动程序:
/***开始*****************************************************/
int _tmain(int argc, _TCHAR* argv[])
{
00401020  push        ebp              建立堆栈帧
00401021  mov         ebp,esp          存入栈基地址,运行后EBP = 0012FEE4

                                       (表明默认堆栈大小约为1兆)
00401023  sub         esp,44h          空出一块堆栈区,不知道是干什么的,可有高人指点?

×××××××××××××××××××××
在一篇vc6的汇编调试文章中看到main中变量存储于此堆栈中,但是我在vc7调试发现iresult地址根本不在堆栈范围之内,不知作何解释
×××××××××××××××××××××
00401026  push        ebx              保护现场
00401027  push        esi 
00401028  push        edi 
 int iResult = add(123, 456);
00401029  push        1C8h             参数入栈
0040102E  push        7Bh 
00401030  call        add (401000h)    执行函数调用,按F11跳到本文蓝色处

×××××××××××××××××××××
call指令详解:
call指令是push和jmp的结合,先执行push eip将当前地址入栈(函数调用完毕需要用这个地址返回),然后调用jmp指令。因为普通指令无法对eip操作,所以在很多病毒程序中常有如下语句:
       call            @@get_eip
@@get_eip:  
       pop  ebp ;取得eip

×××××××××××××××××××××
00401035  add         esp,8            释放123和456变量所占堆栈
00401038  mov         dword ptr [iResult],eax           从eax取出计算结果
 printf(" ************ ");           下面是一个函数的测试
0040103B  push        offset string " ************ " (4060FCh)        变量地址入栈
00401040  call        printf (401051h) 执行call调用函数
00401045  add         esp,4            变量地址出栈

 
 return 0;
00401048  xor         eax,eax          使eax为0,eax就是返回给操作系统的值
}
0040104A  pop         edi 
0040104B  pop         esi 
0040104C  pop         ebx              恢复现场
0040104D  mov         esp,ebp          平衡堆栈
0040104F  pop         ebp              释放堆栈帧
00401050  ret                          返回操作系统调用处

 
函数定义:
 int __cdecl add(int a, int b)
{
00401000  push        ebp         建立堆栈帧
00401001  mov         ebp,esp     存入栈基地址
00401003  sub         esp,44h     开辟变量使用的堆栈区,供函数内部变量使用

                                  执行前ESP = 0012FE84,执行后ESP = 0012FE40
×××××××××××××××××××××
此处可以打开内存0x0012FE8C,看到 7b 00 00 00 c8 01 00 00,这就是我们传入的123(0x0012fe8c处)和456(0x0012fe90处)变量
×××××××××××××××××××××
00401006  push        ebx         保护现场
00401007  push        esi 
00401008  push        edi 
 int c;
 c = a + b;
00401009  mov         eax,dword ptr [a]   第一个参数,也就是[ebp+8]
0040100C  add         eax,dword ptr [b]   第二个参数,也就是[ebp+c]

0040100F  mov         dword ptr [c],eax   c变量在栈中,地址为0x0012fe80,就是变量堆栈区顶部
 return c;
00401012  mov         eax,dword ptr [c]   计算结果存入eax
}
00401015  pop         edi        回复现场
00401016  pop         esi 
00401017  pop         ebx 
00401018  mov         esp,ebp    平衡堆栈,回收变量堆栈区
0040101A  pop         ebp        释放堆栈帧
0040101B  ret                    回到调用地址,读者从这里转到粉红色处接着看

/***结束*****************************************************/
相关阅读 更多 +
排行榜 更多 +
跳跃大联盟

跳跃大联盟

休闲益智 下载
瓜米

瓜米

游戏工具 下载
克隆人联盟

克隆人联盟

动作格斗 下载