C程序使用不同函数调用约定调用汇编子过程

如转载,请注明出处:http://blog.csdn.net/zhangyang0402/archive/2010/05/01/5549266.aspx

 

开发工具:VC ++ 6.0  MASM32

 

一、__cdecl调用方式

 

1.  VC中新建Win32 Console Application, TestASM

 

2.  新建test.c

#include<stdio.h>

extern void swap(int *px, int *py);

int main(void)

{

       int a=1, b=2;

       printf("before swaping, a=%d, b=%d/n", a, b);

       swap(&a, &b);

       printf("after  swaping, a=%d, b=%d/n", a, b);

    return 0;

}

 

3.  使用UltraEdit编辑汇编程序swap.asm

.386

.MODEL FLAT, C

OPTION CASEMAP:NONE

.CODE

  swap PROC a:DWORD, b:DWORD

    PUSH ESI

    PUSH EDI

      MOV ESI, [EBP+8]

     MOV EAX, [ESI]    ;参数1的值->EAX

      MOV EDI, [EBP+12]

      XCHG EAX, [EDI]

      MOV [ESI], EAX

      POP EDI

      POP ESI

      RET

  swap ENDP

END

 

4.  swap.asm添加到TestASM工程中

VC->Project->Add to project->Files, 文件类型选择“所有文件”,选中汇编源文件swap.asm并添加到工程
或直接编译swap.asm,将生成的swap.obj拷贝到工程目录下

5.  VC中设置汇编程序编译选项

VCFileView中,右击swap.asm->Settings, 切换到“Custom Build”选项卡,

在“Command”中输入:ml /c /coff  $(InputName).asm

Output”中输入 $(InputName).obj

 

6.  编译链接执行

双击test.c->Compile 生成test.obj

双击swap.asm->Compile 生成swap.obj

然后Build 生成TestASM.exe

最后执行

结果如下:

before swaping, a=1, b=2

after  swaping, a=2, b=1

Press any key to continue

 

二、__stdcall调用方式

1.C源程序

#include<stdio.h>

extern void __stdcall swap(int *px, int *py);

int main(void)

{

       int a=1, b=2;

       printf("before swaping, a=%d, b=%d/n", a, b);

       swap(&a, &b);

       printf("after  swaping, a=%d, b=%d/n", a, b);

    return 0;

}

 

2. 汇编源程序

.386

.MODEL FLAT, STDCALL

OPTION CASEMAP:NONE

.CODE

  swap PROC a:DWORD, b:DWORD

    PUSH ESI

    PUSH EDI

      MOV ESI, [EBP+8]

     MOV EAX, [ESI]    ;参数1的值->EAX

      MOV EDI, [EBP+12]

      XCHG EAX, [EDI]

      MOV [ESI], EAX

      POP EDI

      POP ESI

      RET

  swap ENDP

END

 

三、总结

 

函数调用约定

__cdecl

__stdcall

相同点

自右向左反序入栈

不同点

函数名修饰符

_FunctionName

_FunctionName@参数字节数

谁清理堆栈参数

调用者

被调用者

 

1.       自右向左反序入栈

0040105B   lea         edx,[ebp-8]

0040105E   push        edx

0040105F   lea         eax,[ebp-4]

00401062   push        eax

2.       函数名修饰符

使用dumpbin工具查看swap.obj

__cdecl调用约定: __swap

__stdcall调用约定:__swap@8

 

3.       谁清理堆栈参数

(1)__cdecl调用约定

调用者来清理,如下面的add esp, 8

8:        swap(&a, &b);

0040105B   lea         edx,[ebp-8]

0040105E   push        edx

0040105F   lea         eax,[ebp-4]

00401062   push        eax

00401063   call        @ILT+5(_swap) (0040100a)

00401068   add         esp,8

 

(2)__stdcall调用约定

被调用者负责清理,如下面的ret 8

7:        swap(&a, &b);

0040105B   lea         edx,[ebp-8]

0040105E   push        edx

0040105F   lea         eax,[ebp-4]

00401062   push        eax

00401063   call        @ILT+0(_swap@8) (00401005)

_swap@8:

004010AC   push        ebp

004010AD   mov         ebp,esp

004010AF   push        esi

004010B0   push        edi

004010B1   mov         esi,dword ptr [ebp+8]

004010B4   mov         eax,dword ptr [esi]

004010B6   mov         edi,dword ptr [ebp+0Ch]

004010B9   xchg        eax,dword ptr [edi]

004010BB   mov         dword ptr [esi],eax

004010BD   pop         edi

004010BE   pop         esi

004010BF   leave

004010C0   ret         8

 

 

你可能感兴趣的:(C程序使用不同函数调用约定调用汇编子过程)