设为首页 加入收藏

TOP

3.4.3 在C程序中调用汇编函数
2013-10-12 06:48:32 来源: 作者: 【 】 浏览:109
Tags:3.4.3 程序 调用 汇编 函数

3.4.3  在C程序中调用汇编函数

从C程序中调用汇编程序函数的方法与汇编程序中调用C函数的原理相同,但Linux 内核程序中不常使用。调用方法的着重点仍然是对函数参数在栈中位置的确定上。当然,如果调用的汇编语言程序比较短,那么可以直接在C程序中使用上面介绍的内联汇编语句来实现。下面举例说明编制这类程序的方法。包含两个函数的汇编程序callee.s如下。

/*
本汇编程序利用系统调用sys_write()实现显示函数int
mywrite(int fd, char * buf, int count)。
函数int myadd(int a, int b, int * res) 用于执行
a+b = res运算。若函数返回0,则说明溢出。
注意:如果在现在的Linux系统(如RedHat 9)下编译,则请
去掉函数名前的下划线'_'。
*/
SYSWRITE = 4 # sys_write()系统调用号。
.global _mywrite, _myadd
.text
_mywrite:
pushl   %ebp
movl   %esp, %ebp
pushl    %ebx
movl     8(%ebp), %ebx  # 取调用者第1个参数:文件描述符fd。
movl     12(%ebp), %ecx # 取第2个参数:缓冲区指针。
movl     16(%ebp), %edx # 取第3个参数:显示字符数。
movl     $SYSWRITE,%eax # %eax中放入系统调用号4。
int   $0x80 # 执行系统调用。
popl     %ebx
movl     %ebp, %esp
popl     %ebp
ret
_myadd:
pushl    %ebp
movl     %esp, %ebp
movl     8(%ebp), %eax  # 取第1个参数a。
movl     12(%ebp), %edx # 取第2个参数b。
xorl     %ecx, %ecx  # %ecx为0表示计算溢出。
addl     %eax, %edx  # 执行加法运算。
jo    1f  # 若溢出则跳转。
movl     16(%ebp), %eax # 取第3个参数的指针。
movl     %edx, (%eax)   # 把计算结果放入指针所指位置处。
incl     %ecx  # 没有发生溢出,于是设置无溢出返回值。
1:movl     %ecx, %eax  # %eax中是函数返回值。
movl     %ebp, %esp
popl     %ebp
ret

该汇编文件中的第1个函数mywrite()利用系统中断0x80调用系统调用sys_write(int fd, char *buf, int count)实现在屏幕上显示信息。对应的系统调用功能号是4(参见include/ unistd.h),3个参数分别为文件描述符、显示缓冲区指针和显示字符数。在执行int 0x80之前,寄存器%eax中需要放入调用功能号(4),寄存器%ebx、%ecx和%edx要按调用规定分别存放fd、buf和count。函数mywrite()的调用参数个数和用途与sys_write()完全一样。

第2个函数myadd(int a, int b, int *res)执行加法运算。其中参数res是运算的结果。函数返回值用于判断是否发生溢出。如果返回值为0表示计算已发生溢出,结果不可用。否则计算结果将通过参数res返回给调用者。

注意:如果在现在的Linux系统(如RedHat 9)下编译callee.s程序,则请去掉函数名前的下画线"_"。调用这两个函数的C程序caller.c如下所示。

/*
调用汇编函数mywrite(fd, buf, count)显示信息;
调用myadd(a, b, result)执行加运算。
如果myadd()返回0,则表示加函数发生溢出。首先显示
开始计算信息,然后显示运算结果。
*/
01 int main()
02 {
03char buf[1024];
04int a, b, res;
05char * mystr = "Calculating...\n";
06char * emsg  = "Error in adding\n";
07
08a = 5; b = 10;
09mywrite(1, mystr, strlen(mystr));
10if (myadd(a, b, &res)){
11  sprintf(buf, "The result is %d\n", res);
12  mywrite(1, buf, strlen(buf));
13} else {
14  mywrite(1, emsg, strlen(emsg));
15}
16return 0;
17 }
该函数首先利用汇编函数mywrite()在屏幕上显示开始计算的信息"Calculating...",然后调用加法计算汇编函数myadd()对a和b两个数进行运算,并在第3个参数res中返回计算结果。最后利用mywrite()函数把格式化的结果信息字符串显示在屏幕上。如果函数myadd()返回0,则表示加函数发生溢出,计算结果无效。这两个文件的编译和运行结果如下:
[/usr/root]# as -o callee.o callee.s
[/usr/root]# gcc -o caller caller.c callee.o
[/usr/root]# ./caller
Calculating...
The result is 15
[/usr/root]#


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇3.4.2 在汇编程序中调用C函数 下一篇3.4.1 C函数调用机制

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: