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

7 篇文章 0 订阅

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

    yasm的下载

    在http://yasm.tortall.net/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);
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值