在汇编程序中调用C函数

一、参数如何传递

汇编程序调用C函数时,函数的入口参数使用栈来传送,参数的传递顺序是从右到左。即函数最后(最右边的)一个参数先入栈,而最左边的第一个参数最后入栈,然后执行 CALL 指令去调用C函数。

二、参数的清除

在C函数返回后,汇编程序需要把先前压入栈中的函数参数清除掉,即调用者负责清除参数占用的栈空间。

比如要调用的C函数和要传递的参数是printSomething (arg1, arg2, arg3, arg4);
那么在汇编程序中应该这样写:

pushl arg4
pushl arg3
pushl arg2
pushl arg1
call  printSomething
addl  $0x10, %esp

三、返回值的传递

C函数的返回值如果是32位整数,则保存在eax寄存器;如果是64位整数,则保存在edx:eax寄存器。

四、关于返回地址

在执行CALL指令时,CPU会把CALL指令的下一条指令的地址(返回地址)压入栈中(见图中 EIP)。

在汇编程序中调用C函数_第1张图片

五、关于栈的切换

如果调用还涉及到代码特权级变化,那 么CPU还会进行栈切换,这个过程就比较复杂了。可以参考我的博文:通过调用门进行控制转移

注意:Linux内核中只使用中断门和陷阱门方式处理特权级变化时的调用情况,并没有使用CALL指令来处理特权级变化的情况。

六、用JMP指令代替CALL指令

我们可以不用CALL指令而采用JMP指令来同样达到调用C函数的目的。方法是:在所有参数入栈后,人工把下一条要执行的指令的地址(返回地址)压入栈中,然后直接使用JMP指令跳转到被调用函数的入口地址去执行。当被调用函数执行其最末尾的ret指令时,就会把我们人工压入栈中的返回地址弹出到EIP寄存器中,使执行流程返回到主函数。

参考资料

《Linux内核完全剖析》(赵炯,机械工业出版社,2006)

你可能感兴趣的:(Linux-0.11)