C调用子函数所征用的寄存器

C语言在被编译器编译的过程中,会有生成汇编代码的过程。故而用C语言写一段程序的内部机制跟用汇编代码写一段程序的机制时一样的。比如在子函数中,子函数的返回值存在寄存器eax中,那么对应的汇编代码就是用eax保存子函数的输出值。即在C中已经包含了这个机制,但汇编代码还需要用代码来实现这个用eax保存子函数返回值的机制。其实汇编程序拥有多种方式保存子函数的返回值(全局变量,某个寄存器),只是在C中调用汇编函数时,要符合C原有的种种机制,从而在汇编代码中,用eax寄存器来保存函数的32位返回值。

 

也就是说,要用汇编代码写一个函数,能够供C程序调用,那么这段汇编代码就要符合C语言程序的机制。比如将要返回的值放在eax寄存器中。在C程序中就可以按照C函数的调用方式调用此汇编函数,汇编函数在eax中存的值将自动被系统当成返回值。

 

C程序中调用子函数时,有的寄存器有特殊的作用。C调用子函数所征用的寄存器有:eaxst(0),ebx,ebpespediesi

 

保存函数输出变量,存函数返回值的寄存器:eaxst(0)

eax保存函数的输出值,但若子函数的返回值为32位整型时,eax的值为函数返回值,为64位时用edx:eax保存低。

st(0)用来保存函数的的浮点型输出值,但若子函数返回值为浮点型,st(0)的值为函数返回值。

 

调用子函数前后寄存器值必须不变的有:ebxebpespediesi

ebx被用来保存全局偏移表的地址值。[啥是全局偏移表]

ebp被用来指向父函数中的栈顶。

esp被用来指向在子函数中栈的新栈顶。

ediesi被用作局部寄存器使用。

 

这些寄存器在子函数调用后都不得改变其值。就是说如果在子函数中要用到这些寄存器,那么一定要对这些寄存器原有的值进行备份,使用完这些寄存器后再将备份值还原到各寄存器中。

 

在C中编写汇编函数,在汇编子函数中采取这样的结构:

.section  .text

.type  func,  @function

func:

        pushl  %ebp

        movl  %esp,  %ebp

       subl   $12,   %esp

       pushl  %edi

       pushl  %esi

       pushl  %ebx

 

       <function code>

 

       popl  %ebx

       popl  %esi

       popl  %edi

       movl  %ebp,  %esp

       popl  %ebp

ret

用栈备份对于父函数来说不可改变的寄存器的值,这可以当做在C程序中编写汇编函数的固定结构。如果没有用到某个寄存器,则响应的push和pop的代码就可以省略掉。采取这样的备份,就保证了C语言支持嵌套调用:子函数返回前各寄存器都得到了原来在父函数中的值,从未经改变。

 

可在汇编函数中随意使用的寄存器:ecxedxst(1) ~~ st(7)

 

C Note Over。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值