欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

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

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

弄了几天的C调用汇编子过程,现总结一下。
开发工具: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中设置汇编程序编译选项
在VC的FileView中,右击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

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功