分类:
2010-09-07 22:11:44
首先,如果想从MASM编译的汇编程序调用DJGPP的GCC编译的C程序,这个可能性不大,两个编译出的差异恐怕太大了,本文使用MASM 6.11和TURBO C 3.0作为例子,完成一个从汇编调用C的小范例,这样的调用比较靠谱。
使用过TURBO C的人都知道,TC把编译出来的程序结构分成6种模式:Tiny、Small、Medium、Compact、Large和Huge,不管是汇编调C还是 C调用汇编,都首先要搞清楚使用什么模式,必须要保证汇编编译出的模式和TC编译出的模式一致,否则调用是要出问题;其次要搞清楚参数调用规则,比如 f(a,b),a、b这两个参数是如何传到C程序中f函数下的,解决了这两个问题,剩下的就是如何链接的问题了。
先说第一个问题,TC中的编译模式。
汇编程序的大致模式是这样的:
segment byte public 'code'
assume cs:, ds:
<------------代码段------------------------------------->
ends
segment word public 'data'
<------------初始化的数据段---------------------------->
ends
_bss segment word public 'bss'
<------------未初始化的数据段-------------------------->
_bss ends
end
这些段在TC下各种模式的对应名称如下:
存储模式 在TC下的名称
--------------------------------------------------------------------------
Tiny, Small = _TEXT = _DATA
Compact = _TEXT = _DATA
Medium = _TEXT = _DATA
Large = filename_TEXT = _DATA
Huge = filename_TEXT
= filename_DATA
所以在编写汇编程序时,一定要使用TC中的名称来确定各个段,否则无法链接到一起
第二个问题,参数的传递,TC使用所谓的“C协议”来传递参数,即:将要传递的参数的值,按照逆序(从右向左)压入堆栈,后接返回地址。
比如函数f(a,b),为一个近(near)调用,a和b均为整数(int),调用f后,堆栈中的内容依次为:返回地址、a和b,所以当我们在汇编中使用call f时,要先运行push b和push a两条指令,否则,必然出现混乱。
下面我们实现一个范例。
程序实现了2 + 6 = 8的计算,汇编语言中,向C程序中的函数add_c传递两个参数:a和b,在C程序中完成运算并返回结果给汇编程序。使用Small模式进行编译,下面是汇编部分的程序:
文件名:test.asm
DGROUP GROUP _DATA
ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP
EXTERN _add_c:near
_DATA SEGMENT WORD PUBLIC 'DATA'
PUBLIC _a
_a dw 02h ; int a=2
PUBLIC _b
_b dw 06h ; int b=6
PUBLIC _c
_c dw 00h ; int c=0
_DATA ENDS
_TEXT SEGMENT BYTE PUBLIC 'CODE'
PUBLIC _main
_main proc near
push bp
mov bp, sp
push _b
push _a
call _add_c
add sp, 4
mov _c, ax
mov sp, bp
pop bp
ret
_main endp
_TEXT ENDS
END
其中的_main是对应C语言里的main()函数,这样和C程序链接到一起时才有启动位置(后面可以看到,我们要使用TC下的启动代码)。
下面是C程序。
文件名:add_c.c
add_c(int x, int y) {
printf("in the add_c(x, y); \n");
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("%d + %d = %d\n", x, y, x + y);
return(x + y);
}
这段程序实在没有什么好解释的。
下面我们要编译这两个程序,汇编程序的编译没有什么特别的,使用masm编译即可。
C程序其实也没什么特别的,只是要注意设成Small模式即可,只编译不要链接。
下面我们来把这两个编译好的OBJ文件链接到一起。
tlink \tc\lib\c0s.obj test add_c, test, test, \tc\lib\emu \tc\lib\cs
这个是我们前面提到的要解决的三个问题的最后一个,我们来解释一下:
tlink:TC下的链接程序
\tc\lib\c0s.obj:TC的Small模式下的启动代码,如果在TC下编译会自动加进来,如果你的TURBO C不是存放在\tc目录下,请使用正确的路径。
test add_c:指两个已经编译好的OBJ文件test.obj和add_c.obj
test:链接好后的EXE文件为test.exe
test:声称的MAP文件为test.map
\tc\lib\emu \tc\lib\cs:是我们这个程序需要的TC下的库函数,这两个库在\tc\lib目录下可以找到。
执行结果:
希望此文能给文章开头提到的那位台湾朋友一些帮助。
chulia200020012010-09-07 22:13:24
DOS主引导扇区分析 http://hengch.blog.163.com/blog/static/10780067200971610626606/ 博主的所有文章分类列表 http://hengch.blog.163.com/blog/static/107800672009139423644/