这篇心得是大2写的。在整理硬盘的时候突然发现。虽然已经过时了,但是还有点小意义,现保存到我的BLOG上。
汇编与C混合编程
比如写一个c程序调用汇编程序的函数
/*c代码ci.c*/
extern int cyx(int a,int b);
main()
{
printf("answer is:%d",cyx(2,3);
getch();
}
;相应的汇编代码cia.asm
;try c invoke asm
;the function prototype in c language is : int cyx(int a,int b);
.model small
_TEXT segment word public 'CODE'
assume cs:_TEXT
public _cyx
_cyx proc far
push bp
mov bp,sp
push bx
mov ax,[bp+6] ;int a
mov bx,[bp+8] ;int b;
add ax,bx
pop bx
pop bp
ret
_cyx endp
_TEXT ends
end
名称必须加下划线。segment必须是_TEXT
这样才能正确连接
编译cia.asm为cia.obj 拷贝到turboc的目录。
它的命令是masm /mx ca.obj 。其中/mx是对大小写敏感
编译ci.c为ci.obj
新建一个tc工程文件名字为ci.prj
在文件中输入
ci.obj
cia.obj
保存
打开ci.c 在project菜单中设置工程名字为ci.prj
ctrl+f9编译。
解释一下参数的存取。c在调用过程中,将参数从右到左压栈。所以原代码先压3,再压2,
再执行call far ptr _cyx,这样就把下一条指令段值,IP压栈。现在的堆栈情况是
|___ 3 ___|
|________|
|___2____|
|________|
|__cs____|
|________|
|___ip___ |
|________|
进入子程序,再压入bp
mov bp,sp 堆栈情况是
|___ 3 ___|
|________|<--bp+8
|___2____|
|________|<-----bp+6
|__cs____|
|________|
|___ip___ |
|________|
|___ bp__ |
|________|<----bp
按理说如果把_cyx改成 _cyx proc near 那么应该变成近调用,在堆栈中就只有ip,那么第一个参数应该是
bp+4,但我试了,改了不行,可能tc默认的就是远调用。
至于为什么不行。还有为什么用大模式不行,为什么一定要写成_TEXT SEGMENT WORD PUBLIC 'CODE'
我想这个和编译器有关。
windows下C和汇编的混合。
先写一个汇编程序,以这个程序作为入口点调用C中的函数
.586
.model flat
.data
copyright db "hello copyright!"
.code
extern C main:near
extern C TerminateProcess@8:near
extern C GetCurrentProcess@0:near
public STARTCODE
STARTCODE proc near c
call main
push eax
call GetCurrentProcess@0
push eax
call TerminateProcess@8
STARTCODE endp
end STARTCODE
这个程序必须到masm32上编译 ,编好后保存为asmic.asm ,生成asmic.obj
再用vc写一个C程序。asmic1.c
#include "windows.h"
int main()
{
MessageBox(NULL,"TEXT","GOOD",0);
return 0;
}
编译生成asmic1.obj
在dos下执行下面即可
link /subsystem:windows /libpath:D:/Progra~1/Micros~1/VC98/Lib user32.lib asmic.obj asmic1.obj