mingw nasm c调用汇编 汇编调用c
说明:
一直没实践过 c和汇编函数的互相调用,上网搜了一下,大体上是你抄我,我抄你. 抄的不亦乐乎.至于为什么该这样调用楞是屁也没放一个,给我广大程序员带来了多少困扰.今天自己实践了一下汇编和c的互相调用,当然遇到的困难不少,还好够机警总算解决了,也懂了不少! 严重鄙视网上的抄袭作风,真恶心.
汇编和c互相调用的原理:
以下这些话都是我自己总结的,错误还望不吝赐教,当然本人不欢迎侮辱的赐教.
要想汇编和c实现互调,必须要达到的第一步就是. asm汇编程序生成obj文件 c程序生成obj文件 .所谓的obj文件,就是所谓的链接文件,当然我们要做的就是链接这一步 了!!!
要想正确的链接c和汇编的obj文件可不是件容易的事情,当然出错的重点大多都是在汇编里面.为什么呢?
因为汇编里面所有的符号都是自己写的,而且生成obj以后的符号也不会变.但是c不同 c的函数 比如自定义 pt()生成obj文件后 打开obj文件一看 显示的是_pt.
因此要想正确的链接两个obj就需要了解链接器(如 mingw)的习惯了.其实这个规律很简单!只要保证汇编程序里面的符号和c生成的obj里面的符号一致即可了.
比如我asm定义MessageBoxA该符号,但是链接的时候是不通过的,因为(mingw)不认识该符号只认识_MessageBoxA@16.至于如何知道的 只需要在c中简单的调用一
下MessageBoxA然后生成该c的obj,以16进制的方式打开该obj搜索MessageBoxA你就可以看到真正的符号是_MessageBoxA@16所以为了正确的链接汇编里面调用
的符号必须和链接器要求的一致!
下面贴出简单的测试代码:
一 main.c:
#include <stdio.h> #include<windows.h> void message();//从汇编 中导出的函数 需要声明 才可以使用 当然不声明也可以使用 这是因为obj中有该符号 最好申明一下 //c函数 因为 c式的 函数 编译出函数 符号一般加 _ 所以 在汇编里显示为 _prt //当然 如果不确定的话 可以打开编译的 .obj 链接文件 看看 符号的名字 一切 以.obj链接文件的符号为准 因为我们需要做的是链接这一步!! void prt() { printf("我是 c 函数 汇编调用输出成功 .... \n"); } void main() { message();//c调用的 汇编 函数 message //MessageBoxA(0,"","",0); 如果不知道 MessageBoxA在汇编的符号 可以查看 该c中 obj的符号 这样的符号肯定是正确的了 }
二 message.asm
global _message ; 从汇编中导出的函数 给c 使用 extern _MessageBoxA@16 ;导入api 注意符号的问题 extern _prt ;从c中导入的函数 [section .data] ; 数据在此 szTitle db "我是标题 hello",0 szCon db "我是显示的内容",0 [section .text] ; 代码在此 ;global _main ; exe入口函数,同样要加下划线 当然 入口函数也可以放在 asm 中 只要 link 可以识别即可 ;当然 入口函数 可以放在 asm 中 也可以放在 c中 放在 asm需要 注意 符号的问题 毕竟每个编译器 需要的符号可能是不一样的 不能一味的死记 _message: ;c 调用汇编 的函数 当然也得注意 调用约定的清栈 规则 否则很容易出错 push ebp mov ebp,esp push 0 push szTitle push szCon push 0 call _MessageBoxA@16 call _prt;此处 汇编 调用 c 函数 mov esp,ebp pop ebp ret
三 makefile
all:
nasm -f win32 message.asm -o message.obj
gcc -c main.c -o main.obj
gcc message.obj main.obj -o main.exe
clean :
rm *.obj *.exe
四 如何编译
a. 首先 你得学会 nasm 该编译器和 基本的汇编语法 并编译成 win32 obj 文件
b. c程序 也得编译成obj文件
c. 至于链接器如何选择 我选的是windows版的gcc编译器 mingw
d. 当然还得需要解决错误的能力 和毅力