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

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值