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函数
- global _sum ;全局函数声明,表示这个函数要被外部文件调用,注意下划线,c文件或cpp文件中相应函数去掉下划线
-
- _sum:
-
- push ebp ;保护ebp指针
-
- mov ebp,esp
-
- mov eax,[ebp+8] ;第一个入口参数int a
-
- mov ebx,[ebp+12];第二个入口参数int b
-
- add eax,ebx
-
- pop ebp ;恢复ebp指针
-
- ret ;调用者平衡堆栈
在工程中添加项sum_asm.asm,将内容写入即可
c文件调用汇编sum函数
- //ctest.c
- #include <stdio.h>
-
- int sum(int, int);//函数声明
-
- int main()
- {
- int c;
- c = sum(2,5);
- printf("%3d\n",c);
- return 0;
- }
cpp文件调用汇编sum函数
- //ctest.cpp
- #include <stdio.h>
-
- //int sum(int, int);
- extern "C" int _cdecl sum(int, int);//函数声明
-
- int main()
- {
- int c;
- c = sum(2,5);
- printf("%3d\n",c);
- return 0;
- }
_stdcall调用约定
汇编函数不一样了注意函数名_sum@8和ret 8都表示参数的大小(字节数),_stdcall和_cdecl的区别是_stdcall是被调用者也就是这边的sum函数平衡堆栈(ret 8的作用),
而_cdecl是调用者也就是这边的main函数平衡堆栈,被调用者(sum函数)不需要自己平衡堆栈,所以只需要ret即可。
- global _sum@8 ;全局函数声明,表示这个函数要被外部文件调用
-
- _sum@8:
-
- push ebp ;保护ebp指针
-
- mov ebp,esp
-
- mov eax,[ebp+8] ;第一个入口参数int a
-
- mov ebx,[ebp+12];第二个入口参数int b
-
- add eax,ebx
-
- pop ebp ;恢复ebp指针
-
- ret 8 ;被调用者平衡堆栈
c文件调用sum函数
- //ctest.c
- #include <stdio.h>
-
- int _stdcall sum(int, int);
- //extern "C" int _stdcall sum(int, int);
-
-
- int main()
- {
- int c;
- c = sum(2,5);
- printf("%3d\n",c);
- return 0;
- }
cpp文件调用sum函数
- //ctest.cpp
- #include <stdio.h>
-
- //int _stdcall sum(int, int);
- extern "C" int _stdcall sum(int, int);
-
-
- int main()
- {
- int c;
- c = sum(2,5);
- printf("%3d\n",c);
- return 0;
- }
3.不同调用约定下汇编中调用C或Cpp
_cdecl调用约定
- extern _myprint
- global _myprint_asm
- _myprint_asm:
- push ebp ;保护ebp指针
- mov ebp,esp
- mov eax,[ebp+8] ;第一个入口参数int VAR1
- push eax ;保护ebp指针
- call _myprint ;调用C函数myprint
- add esp ,4 ;调用者平衡堆栈
- pop ebp ;恢复ebp指针
- ret ;
观察上面可以看到在_cdecl调用约定下,由调用者(此处是汇编语言中的_myprint_asm函数)平衡堆栈(add esp,4)
- #include <stdio.h>
-
- extern "C" void _cdecl myprint(int a) //此处为cpp时,若是c时可以将extern "C"去掉
- {
- printf("myprint %d\n",a);
- }
-
- extern "C" void _cdecl myprint_asm(int);//同上
-
- void main()
- {
- myprint_asm(16);
- }
_stdcall调用约定
- extern _myprint@4
- global _myprint_asm@4
- _myprint_asm@4:
- push ebp ;保护ebp指针
- mov ebp,esp
- mov eax,[ebp+8] ;第一个入口参数int VAR1
- push eax ;保护ebp指针
- call _myprint@4
- pop ebp ;恢复ebp指针
- ret 4 ;调用者平衡堆栈
注意其中的几处@4以及最后的ret4(相对于main函数,_myprint_asm是被调用者)
- #include <stdio.h>
-
- extern "C" void _stdcall myprint(int a)
- {
- printf("myprint %d\n",a);
- }
-
- extern "C" void _stdcall myprint_asm(int);
-
- void main()
- {
- myprint_asm(16);
- }
|