03-C函数与汇编的相互调用

抛个砖:汇编中如何调用C函数?

引个玉:相互调用有四种组合:

1.C函数之间的相互调用
2.汇编例程的相互调用
3.C函数调用汇编例程
4.汇编例程调用C函数
但这里,主讲1和4。因为2与4类似,1与3类似

1.C函数调用机制

exch.c源文件:
  void swap(int *a, int *b){
        int c;
        c = *a, *a = *b; *b = c;
    }
    int main(){
        int a, b;
        a = 16, b = 32;
        swap(&a, &b);
        return (a - b);
    }

exch.c的汇编代码(AT&T风格)
AT&T风格
小结:这里说说编译器的聪明之处,传递地址时使用 lea 指令计算的地址值并没有保存在调用者的栈中,而是两个寄存器。减少了内存访问次数。此外,使用mov将参数地址压入被调用者栈而不是用push压入调用者栈中,减少了所需系统周期数(push 肯定比 mov 所需周期数多)

基于exch.c 再改造一下,如果传递结构体,如何利用栈实现呢?

exch_struct.c
typedef struct{
	int *a;
	int *b;
}ts_struct;
void exch_struct(ts_struct ts){
	int c;
	c = *ts.a;
	*ts.a = *ts.b;
	*ts.b = c;
}
int main(void){
	ts_struct ts;
	int a = 10, b = 20;
	ts.a = &a;
	ts.b = &b;
	exch_struct(ts);
	return 0;
}

exch_struct.c对应的汇编代码:

函数参数为结构体的调用
C函数调用机制总结:
即使参数是结构体(或类)这类大的对象,也能通过栈机制(+寄存器)完成数据交换(调用者通过参数,被调用者通过返回值或指针交换)。

2.汇编中调用C函数

将调用函数的参数逆序(从右至左)压入调用者的栈中,再执行call指令,即如下图
调用函数时压栈的参数
小结:汇编中调用C函数比较自由,原因有二
1.只要在栈中适当位置的内容都可以作为参数供C函数使用
2.根本不用CALL指令,而采用JMP指令来达到调用函数的目的(前提需把下一条要执行的指令地址人工压栈中)
提前透露一点:
Linux内核利用了在被调用者中,传递的参数在栈中是连续分布的。由此可以只传入参数列表的几个,其它参数按连续性分布特点依次向上取得(以后的文章会有讲解)。

参考资料:
《Linux内核完全剖析——基于0.12内核》第3章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值