注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风雨夜归人

专业收集资料,个人爱好!

 
 
 

日志

 
 

逆向_第三课  

2010-03-10 16:22:30|  分类: 逆向 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
   说完利用堆栈传递参数了,下面该说说使用寄存器传递参数的话题了.寄存器传递传输的方式并没有一个标准,所有与平台相关的方法都是由IDE(也就是编译器)开发人员制定的.尽管没有统一的标准,但绝大多数编译器提供商都在不对兼容性声明的情况下,遵循相应的规范,吉fastcall规范._fastcall顾名思义,特点就是快,因为他是靠寄存器来传递参数的.
       不同编译器实现的fastcall稍有不同,如Microsoft Visual C++编译器采用fastcall规范传递参数时,最左边的两个不大于4个字节(DWORD)的参数分别放在ecx和edx寄存器.当寄存器用完后,就要使用堆栈,其余参数仍然按照从右到左的顺序压入堆栈,被调用的函数在返回前清理传送参数的堆栈.浮点值 员指针和int64类型总是通过对战来传递的.而Borland Delphi/C++编译器总是通过将寄存器来传递参数的,其最左边的三个不大于4个字节(DWORD)的参数分别放在eax  edx  和 ecx寄存器,寄存器用完后,参数按照从左到右的PASCAL方式来压栈.另外一款编译器Watcom C总是通过寄存器来传递参数的,严格为每一个参数分配一个寄存器,默认时第一个参数用eax,第二个参数用edx,第三个参数用ebx,第四个参数用ecx,如果寄存器用完了,就会用堆栈来传递参数.Watcom C可以由程序员指定任意一个寄存器传递参数,因此,其参数实际上可能通过任何寄存器进行传递.
        来看一个手动指定fastcall调用参数的实例:
C源码如下:
int _fastcall Add(char,long,int,int);
main(void)
{
Add(1,2,3,4);
return 0;
}
int _fastcall Add(char a,long b,int c,int d);
{
return (a+b+c+d);
}
这个反汇编后的代码
00401000     /$  55            push    ebp
00401001     |.  8BEC          mov     ebp, esp
00401003     |.  6A 04         push    4                                ;  后面两个参数从右到左入栈,先压入a
00401005     |.  6A 03         push    3                                ;  再将第三个参数数值3入栈
00401007     |.  BA 02000000   mov     edx, 2                           ;  再将第二个参数数值2放入edx
0040100C     |.  B1 01         mov     cl, 1                            ;  传递第一个参数(字符类型的变量是8位大小)
0040100E     |.  E8 04000000   call    fastcall.00401017                ;  调用Add()函数
00401013     |.  33C0          xor     eax, eax
00401015     |.  5D            pop     ebp
00401016     \.  C3            retn
00401017     /$  55            push    ebp
00401018     |.  8BEC          mov     ebp, esp
0040101A     |.  83EC 08       sub     esp, 8                           ;  为局部变量分配8个字节
0040101D         8955 F8       mov     dword ptr ss:[ebp-8], edx        ;  第二个参数放到局部变量[ebp-08]中
00401020         884D FC       mov     byte ptr ss:[ebp-4], cl          ;  第一个参数放到局部变量[ebp-4]中
00401023     |.  0FBE45 FC     movsx   eax, byte ptr ss:[ebp-4]         ;  将字符型数据扩展成一个双字
00401027     |.  0345 F8       add     eax, dword ptr ss:[ebp-8]        ;  将左边2个参数相加
0040102A     |.  0345 08       add     eax, dword ptr ss:[ebp+8]        ;  相加之后的和(放到eax中)再加第三个参数
0040102D     |.  0345 0C       add     eax, dword ptr ss:[ebp+C]        ;  最后再将eax的结果加上第四个参数
00401030     |.  8BE5          mov     esp, ebp
00401032     |.  5D            pop     ebp
00401033     \.  C2 0800       retn    8
         另一个调用规范thiscall也用到了寄存器传递参数.thiscall是C++中的非静态类成员函数的默认调用约定,对象的每个函数隐含接受this参数.采用thiscall约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,只是另外通过寄存器ecx传送一个额外的参数:this指针.
定义一个类,并在类中定义一个成员函数:
class CSun
{
public:
int Add(int a,int b) //实际Add原型如下形式:Addd(this,int a,intb)
{
return (a+b)
}
};
void main()
{
CSum sum;
sum.Add(1,2);
}
看看他反汇编后的代码:
00401004  |.  6A 02         push    2                                ;  传递第三个参数
00401006  |.  6A 01         push    1                                ;  传递第二个参数
00401008  |.  8D4D FC       lea     ecx, dword ptr ss:[ebp-4]        ;  this指针通过ECX寄存器传递
0040100B  |.  E8 10000000   call    VF.00401020                      ;  调用函数sum.Add(1,2)
00401010  |.  8BE5          mov     esp, ebp
00401012  |.  5D            pop     ebp
00401013  \.  C3            retn
sum.Add()函数实现部分反汇编代码:
00401020  /$  55            push    ebp
00401021  |.  8BEC          mov     ebp, esp
00401023  |.  51            push    ecx
00401024  |.  894D FC       mov     dword ptr ss:[ebp-4], ecx
00401027  |.  8B45 08       mov     eax, dword ptr ss:[ebp+8]
0040102A  |.  0345 0C       add     eax, dword ptr ss:[ebp+C]
0040102D  |.  8BE5          mov     esp, ebp
0040102F  |.  5D            pop     ebp
00401030  \.  C2 0800       retn    8
我就不过多分析了,和前面差不多.
  评论这张
 
阅读(541)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017