C++反汇编学习笔记3——函数的调用方式

两年前写的,欢迎大家吐槽!

转载请注明出处。


函数的调用方式

VC++下有三种函数调用方式,分别是:__cdecl 、 __stdcall 、__fastcal。第一种是C/C++默认的函数调用方式,如果不特殊指明用那种方式则默认使用__cdecl,而且只有第一种可以在不定参数的函数下使用,后面的方式指明所使用的函数必须是确定参数的,包括参数的个数和类型。下面就来详细介绍这三种调用方式之间的区别。

1.      __cdecl方式和__stdcall方式的比较

还是从例子开始:

刚开始是两个函数的定义,如下所示:

__stdcall调用:

     8: void __stdcall ShowStd(int nNumber)

     9: {//部分代码略,只看栈平衡的代码

    10: printf("%d\r\n", nNumber);

    11: }

0042B432  ret   4 

__cdecl调用:

    12: void __cdecl ShowCde(int nNumber)

    13: {

    14: printf("%d\r\n", nNumber);

    15: }

0042B482  ret 

这里可以看到__stdcall方式在函数结束时就进行栈平衡操作,ret 4相当于esp+=4。而__cdecl方式却没有,下面再来看main函数中的调用情况:

int main()

{

86:  ShowStd(5);

0042B75E 6A 05                push        5 

0042B760 E8 A9 D9 FF FF       call        ShowStd (42910Eh) 

    87: ShowCde(5);

0042B765 6A 05                push        5 

0042B767 E8 38 DA FFFF       call        ShowCde (4291A4h) 

0042B76C 83 C404             add         esp,4 

}

由函数调用可以看到__cdecl方式是在函数体外面进行栈平衡的,这就是这两个函数调用方式的不同之处,可以用来区分是哪种函数调用,但是也不能完全作为依据,只能做参考。

2.      printf函数在Debug版本和Release版本直接的区别

printf函数的参数不能确定,所以必须以_cdecl方式调用。在Debug版本下,连续的几个printf函数会在每次调用的时候分别进行栈平衡操作,但是在Release版本之下却并非如此,下面就举一个Release版本的例子(Debug版本和上面的调用一样,这里就不再举例):

C语言代码:

printf("Hello");

printf("World");

printf("C++");

printf("\r\n");

相应的反汇编代码:

.text:00401000                 push    offset aHello   ; "Hello "

.text:0

你可能感兴趣的:(C++逆向,c++,反汇编,汇编,黑客,编译器)