分享

利用yasm在vs2008中进行X86汇编与C/C++相互调用

 盛夏流年闪耀 2014-11-04

1.工具的下载以及环境的搭建

    yasm的下载

    在http://yasm./Download.html选择win32.exe,将其改名为yasm.exe,并将其添加至D:\Program Files\Microsoft Visual Studio 9.0\VC\bin下(安装目录不同的对应更改)

    yasm.rules文件下载

    在https://github.com/yasm/yasm/blob/master/Mkfiles/vc9/yasm.rules上复制yasm.rules的内容到记事本,另存为yasm.rules,将其添加至D:\Program Files\Microsoft Visual Studio 9.0\VC\VCProjectDefaults下,此文件夹下还有两个masm.rules(ml.exe的编译规则)和lc.rules

    环境搭建

    新建项目后,右击项目, 选择自定义生成规则,查找现有的,找到刚刚的yasm.rules,选择添加,OK,然后在对话框中就可以看到Yasm汇编器选项,勾上,确定。

2.不同调用约定下C或Cpp调用汇编

_cdecl调用约定

汇编编写的sum函数

  1. global _sum  ;全局函数声明,表示这个函数要被外部文件调用,注意下划线,c文件或cpp文件中相应函数去掉下划线  
  2.   
  3. _sum:  
  4.   
  5.  push ebp        ;保护ebp指针  
  6.   
  7.  mov ebp,esp  
  8.   
  9.  mov eax,[ebp+8] ;第一个入口参数int a  
  10.   
  11.  mov ebx,[ebp+12];第二个入口参数int b  
  12.   
  13.  add eax,ebx  
  14.   
  15.  pop ebp         ;恢复ebp指针  
  16.   
  17.  ret            ;调用者平衡堆栈  

    在工程中添加项sum_asm.asm,将内容写入即可

c文件调用汇编sum函数

  1. //ctest.c  
  2. #include <stdio.h>  
  3.   
  4. int sum(int, int);//函数声明  
  5.   
  6. int main()  
  7. {  
  8.     int c;  
  9.     c = sum(2,5);  
  10.     printf("%3d\n",c);  
  11.     return 0;  
  12. }  


cpp文件调用汇编sum函数

  1. //ctest.cpp  
  2. #include <stdio.h>  
  3.   
  4. //int sum(int, int);  
  5. extern "C" int _cdecl sum(int, int);//函数声明  
  6.   
  7. int main()  
  8. {  
  9.     int c;  
  10.     c = sum(2,5);  
  11.     printf("%3d\n",c);  
  12.     return 0;  
  13. }  

_stdcall调用约定

汇编函数不一样了注意函数名_sum@8和ret 8都表示参数的大小(字节数),_stdcall和_cdecl的区别是_stdcall是被调用者也就是这边的sum函数平衡堆栈(ret 8的作用),

而_cdecl是调用者也就是这边的main函数平衡堆栈,被调用者(sum函数)不需要自己平衡堆栈,所以只需要ret即可。

  1. global _sum@8  ;全局函数声明,表示这个函数要被外部文件调用  
  2.   
  3. _sum@8:  
  4.   
  5.  push ebp        ;保护ebp指针  
  6.   
  7.  mov ebp,esp  
  8.   
  9.  mov eax,[ebp+8] ;第一个入口参数int a  
  10.   
  11.  mov ebx,[ebp+12];第二个入口参数int b  
  12.   
  13.  add eax,ebx  
  14.   
  15.  pop ebp         ;恢复ebp指针  
  16.   
  17. ret 8            ;被调用者平衡堆栈  

c文件调用sum函数

  1. //ctest.c  
  2. #include <stdio.h>  
  3.   
  4. int _stdcall sum(int, int);  
  5. //extern "C" int _stdcall sum(int, int);  
  6.   
  7.   
  8. int main()  
  9. {  
  10.     int c;  
  11.     c = sum(2,5);  
  12.     printf("%3d\n",c);  
  13.     return 0;  
  14. }  

cpp文件调用sum函数

  1. //ctest.cpp  
  2. #include <stdio.h>  
  3.   
  4. //int _stdcall sum(int, int);  
  5. extern "C" int _stdcall sum(int, int);  
  6.   
  7.   
  8. int main()  
  9. {  
  10.     int c;  
  11.     c = sum(2,5);  
  12.     printf("%3d\n",c);  
  13.     return 0;  
  14. }  


3.不同调用约定下汇编中调用C或Cpp

_cdecl调用约定

  1. extern _myprint  
  2. global _myprint_asm  
  3. _myprint_asm:  
  4.      push ebp        ;保护ebp指针  
  5.      mov ebp,esp  
  6.      mov eax,[ebp+8] ;第一个入口参数int VAR1  
  7.      push eax       ;保护ebp指针      
  8.      call _myprint  ;调用C函数myprint  
  9.      add esp ,4      ;调用者平衡堆栈  
  10.      pop ebp         ;恢复ebp指针  
  11.      ret            ;  

观察上面可以看到在_cdecl调用约定下,由调用者(此处是汇编语言中的_myprint_asm函数)平衡堆栈(add esp,4)

  1. #include <stdio.h>  
  2.   
  3. extern "C" void _cdecl myprint(int a) //此处为cpp时,若是c时可以将extern "C"去掉  
  4. {  
  5.     printf("myprint %d\n",a);   
  6. }  
  7.   
  8. extern "C" void _cdecl myprint_asm(int);//同上  
  9.   
  10. void main()  
  11. {  
  12.     myprint_asm(16);  
  13. }  

_stdcall调用约定

  1. extern _myprint@4  
  2. global _myprint_asm@4  
  3. _myprint_asm@4:  
  4.      push ebp        ;保护ebp指针  
  5.      mov ebp,esp  
  6.      mov eax,[ebp+8] ;第一个入口参数int VAR1  
  7.      push eax       ;保护ebp指针      
  8.      call _myprint@4    
  9.      pop ebp         ;恢复ebp指针  
  10.      ret  4          ;调用者平衡堆栈  
注意其中的几处@4以及最后的ret4(相对于main函数,_myprint_asm是被调用者)
  1. #include <stdio.h>  
  2.   
  3. extern "C" void _stdcall myprint(int a)  
  4. {  
  5.     printf("myprint %d\n",a);   
  6. }  
  7.   
  8. extern "C" void _stdcall myprint_asm(int);  
  9.   
  10. void main()  
  11. {  
  12.     myprint_asm(16);  
  13. }  



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多