C编译器剖析_6.3.4 汇编代码生成_为函数调用与返回产生汇编代码

本文介绍了C编译器如何为函数调用和返回生成汇编代码,遵循函数调用约定。参数从右向左入栈,返回值根据类型存放在eax或x87栈顶寄存器。编译器处理结构体返回值的特殊方式,以及EmitCall、PushArgument、EmitReturn等关键函数的作用。
摘要由CSDN通过智能技术生成

6.3.4        为函数调用与返回产生汇编代码

    在这一小节中,我们来讨论一下如何为函数调用和函数返回生成汇编代码。函数调用对应的中间指令如下所示:

         //中间指令的四元式: < opcode, DST, SRC1, SRC2>

         <CALL, 用于接收返回值的变量retVal, 函数名func,  参数列表[arg1,arg2, …,argn]>

    让我们先熟悉一下C函数的调用约定CallingConvention,我们需要把参数从右向左入栈(即从argn到arg1依次入栈),不妨记这些参数所占用的总内存为stksize字节。当函数调用返回后,主调函数要负责把这些参数出栈,这可通过形如“addl  stksize, %esp”的汇编指令来实现。{eax, ecx, edx}这3个寄存器要由主调函数负责保存,在产生call汇编指令之前,要对这几个寄存器进行必要的回写操作。而{ebx,esi,edi}这3个寄存器则由被调函数负责保存,UCC编译器会在所有函数的入口处保存这几个寄存器。     为了加快返回值的传递,我们会尽量把返回值放在寄存器中。在x86平台上,按C标准的约定:

    (1) 若返回值为整型,则存于eax寄存器中(我们只考虑32位平台);

    (2) 若返回值为浮点型,则存于x87栈顶寄存器中;

    (3) 按C的语法要求,返回值不可以是数组类型。如果返回值是1、2或4字节的结构体对象,则存于寄存器eax中,若是8字节,则存于[edx: eax]中。若返回值是其他大小的结构体对象,则C编译器会为函数添加结构体指针作为第1个参数,如下所示。

         typedef struct  Data{

             int  num[8];      //共32字节

         } dt;

         dt =  GetData();

         //经C编译器处理后,真正执行的函数调用为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值