C语言与汇编语言的相互调用 1 GNU可以把一些变量值放在CPU寄存器中,即所谓寄存器变量, 节省了CPU访问存储器的时间。
在嵌入汇编语句中把汇编指令的输出直接写到指定的寄存器中,那么此时应该使用局部寄存器变量。
在linux内核中只会使用局部寄存器变量。
在GNU C程序中我们在函数中定义了一个局部寄存器变量如下:
register int res _asm_ ("ax") ;
变量res 希望使用的寄存器是 eax 。 但是变量不一定会存储在该寄存器中,但是如果该变量用作asm的操作数,
那么还是能够保证指定的寄存器被用作该操作数。
2
内联函数 在程序中,一个函数若声明为Inline,那么就可以让gcc把函数的代码集成到调用该函数的代码中去。
这样处理就会节省函数调用时进入/退出的时间开销。
3 C与汇编函数的相互调用
(1) 栈帧结构和控制转移权方式
CPU使用栈来支持函数调用操作,栈被用来传递参数、存储返回信息、临时保存寄存器原有值和存储局部数据。
单个函数调用操作所使用的部分被称为栈帧结构。
栈帧结构由两个指针指定,esp为栈指针,ebp为帧指针。
栈是往小的地方扩展,esp指向当前栈顶的元素,通过使用push和pop可以完成数据的出入栈操作。
4 指令CALL 和 指令RET
指令CALL的作用是把返回地址压入栈中,并且跳转到被调用函数开始处执行。
返回地址是指的是 紧随调用CALL后面一条指令的地址,因此当被调函数返回时,就会从该位置继续执行。
RET指令用于弹出栈顶处的指针并跳到该地址处。在使用该指令之前,首先应该正确处理栈中的内容,使得
当前栈指针所指位置的内容正好是先前CALL指令所保存的返回地址。 另外如果返回值是一个
整数或者是指针的话,
那么寄存器
eax将被默认用来传递返回值。
5 在汇编语言中调用C 函数 调用方法如下:
程序需要首先按照逆向的顺序把函数参数压入到堆栈中,即函数的最右边一个先入栈,
而最左边的一个参数在最后调用指令之前入栈。
函数调用栈如下:
由上图可知一旦参数压栈完毕,则随之将CALL指令后的一个指令地址压栈(即Return Address的值)。