Linux汇编与C互相调用
2015-10-19 18:44
447 查看
一. 概述
汇编通过call指令调用C函数,call指令主要有两个功能:1.将下一条指令的地址保存在栈顶;2.设置eip指向被调用程序代码的开始处。汇编使用ret指令返回,ret的功能是把返回地址从桟里弹出,并转到该地址去执行。
汇编程序调用C函数时,函数的入口参数使用堆栈来传送。
C函数调用时,输入参数采用堆栈方式传递,参数的传递顺序是从右到左,调用者负责清除参数占用的堆栈空间。
C函数的返回值如果是32位整数则存在eax寄存器,如果是64位整数,则存在edx:eax寄存器。
二. 实现
下面的程序由2个文件组成,一个是assembly.s,另外一个是gnuc.c。程序的功能是:在gnuc.c里定义一个全局变量i,在main()函数里调用assembly.s文件里的a_add()函数,将变量i的地址作为参数传进去,在a_add()函数里将变量i的值加1,然后调用gnuc.c文件里的c_add()函数,参数也是变量i的地址,在c_add()函数里将参数所指的值加1,最后main()里打印变量i的值。
gnuc.c的代码:
assembly.s的代码:
运行结果:
可见程序输出2,符合预期效果。
汇编通过call指令调用C函数,call指令主要有两个功能:1.将下一条指令的地址保存在栈顶;2.设置eip指向被调用程序代码的开始处。汇编使用ret指令返回,ret的功能是把返回地址从桟里弹出,并转到该地址去执行。
汇编程序调用C函数时,函数的入口参数使用堆栈来传送。
C函数调用时,输入参数采用堆栈方式传递,参数的传递顺序是从右到左,调用者负责清除参数占用的堆栈空间。
C函数的返回值如果是32位整数则存在eax寄存器,如果是64位整数,则存在edx:eax寄存器。
二. 实现
下面的程序由2个文件组成,一个是assembly.s,另外一个是gnuc.c。程序的功能是:在gnuc.c里定义一个全局变量i,在main()函数里调用assembly.s文件里的a_add()函数,将变量i的地址作为参数传进去,在a_add()函数里将变量i的值加1,然后调用gnuc.c文件里的c_add()函数,参数也是变量i的地址,在c_add()函数里将参数所指的值加1,最后main()里打印变量i的值。
gnuc.c的代码:
1 #include<stdio.h> 2 3 static int i = 0; 4 5 6 void c_add(int *k) 7 { 8 (*k)++; 9 } 10 11 int main(void) 12 { 13 a_add(&i); 14 printf("%d\n",i); 15 16 return 0; 17 }
assembly.s的代码:
1 .section .text 2 .type a_add,@function 3 .globl a_add 4 a_add: 5 pushl %ebp #现场保护 6 movl %esp,%ebp 7 8 movl 8(%ebp),%eax #取得C函数传过来的参数 9 pushl %ecx #保护ecx,用作临时变量 10 movl (%eax),%ecx #取得指针所指的内容 11 addl $1,%ecx #将内容+1 12 movl %ecx,(%eax) #将内容放回指针所指的地方 13 popl %ecx #恢复ecx 14 pushl %eax #压桟,以便传参给C函数 15 call c_add #调用C函数 16 17 addl $4,%esp #清理局部变量 18 popl %ebp #恢复现场 19 ret #返回
运行结果:
可见程序输出2,符合预期效果。
相关文章推荐
- CentOS编译安装boost
- linux 下ab压力测试
- linux下C编程(五)之unsigned 的大坑货和 char 和浮点数
- exit()与_exit()函数的区别(Linux系统中)
- CentOS-6.5系统基础优化附带优化脚本
- Linux快捷键
- linux下C编程(四)之*p++=*q++
- 终端工具putty访问vmware centos系统
- linux下导入、导出mysql数据库命令
- Linux性能评测工具之一:gprof篇
- linux下安装使用protocol buffer编译工具
- linux中快速查找文件
- windows写的脚本到linux里面就不能执行
- windows写的脚本到linux里面就不能执行
- windows写的脚本到linux里面就不能执行
- 使用windows或Linux脚本执行Java项目-JSON例子(二)
- 使用windows或Linux脚本执行Java项目-JSON例子(二)
- linux使用ipvsadm实现LVS
- linux下源码安装软件的一个选项--prefix
- CentOS6.5安装Varnish3.0.3