C语言中调用汇编子过程时参数在栈中是如何调用的


在C语言中嵌入汇编子过程的新手大多都会有一个问题,在用汇编写的子过程(函数)中到底以怎样的形式来获取传进来的参数呢?这里讨论的是堆栈法来实现,下面是我个人的理解:(大神可以一笑而过)

针对这个问题,首先得明白调用一个子过程时栈的变化,因为在传参时首先是将参数压入栈中,而子函数想要调用就直接从栈中弹出即可。

下面是一个简单的分析过程:

首先,在C中调用一个函数,截取如下代码:

i = test(a, b);//在此我们不需要考虑test过程具体的执行内容。 

在执行此语句时,自然先执行:test(a, b); 相当于汇编的:call test
而call指令则会将test所用的参数逆序压入栈中,在此处先压入b,再压入a。

call指令还有一个隐含的操作,即是将返回地址也跟着压入栈中。

至此,call指令本身的操作就执行完毕了,接下来就转交给调用的子过程test执行了。

那么在test中是如何获取传进的参数呢?

在这里已经很显然了,此时栈指针%esp是指向的返回地址,那么第一个参数的地址则是:%esp+4,第二个:%esp+8,如果有更多传参话则依次类推。。。。

那么,我们自己在用汇编写的子过程中调用参数的时候就可以写成

   mov r1, [ esp + 4 ]    //获取参数a
   mov r2, [ esp + 8 ]   //获取参数b
   ..........
   ret

记住了,这是我们自己写的汇编语句,而如果我们的子过程干脆就用c语言写的话,c编译器得到的汇编代码会不会也是这样来获取参数的呢?
答案是否定的。

c编译器产生的汇编语句会有些区别,将代码复制如下:

test:
   push         ebp            //压入旧的帧指针
   mov  ebp, esp            //获取新的帧指针ebp
   mov r1, [ ebp + 8 ]     //获取参数a
   mov r2, [ ebp + 12 ]   //获取参数b
   ......
   ......
   pop        ebp
   ret

 

这里多出来的帧指针是什么呢?简单来说,就是用来在栈中划分当前过程的分界线,还有一个好处就是可以借助其获得参数,此处就是通过  ebp+8 ;ebp+12来获取参数的。

写到这里,大家也能看到我们自己写的汇编子过程与编译器之间的不同了(我们当然也可以按照编译器的习惯来写汇编),最大的不同就是对于帧指针的用法,在c编译器中会默认调用,则也导致最后要pop ebp;

而我们自己写的虽然可以不用压入帧指针,同时在最后也省去了pop ebp;但我们却不能借助帧指针来获取参数了,反正是各有利弊吧,这也与个人的习惯有关。

以上都是我自己的理解,想来应该与实际有些出入,有不对的地方还望指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值