C Compiler anatomy _6.3.4 assembly code Generation _ generate assembly code for function call and return

Source: Internet
Author: User

6.3.4 Generating assembly code for function calls and returns

In this section, let's discuss how to generate assembly code for function calls and function returns. The corresponding intermediate directives for the function call are as follows:

Intermediate instruction of the four-dollar: < opcode, DST, SRC1, src2>

<call, variable retval for receiving return value, function name func, parameter list [ARG1,ARG2, ...,argn]>

Let's familiarize ourselves with the calling convention of the C function callingconvention, we need to put the parameters from right to left into the stack (that is, from argn to arg1 sequentially into the stack), it is worth remembering that these parameters occupy the total memory of stksize bytes. When the function call returns, the key function is responsible for putting these parameters out of the stack, which can be achieved through the assembly instruction of the form "Addl stksize,%esp". {eax, ecx, edx} These 3 registers are to be stored by the key function, and the necessary write-back operations are performed before the call assembly instructions are generated.     The 3 registers of the {Ebx,esi,edi} are stored by the called function, and the UCC compiler saves the registers at the entrance of all functions. To expedite the delivery of the return value, we try to put the return value in the register as much as possible. On the x86 platform, according to the Convention of the C standard:

(1) If the return value is integral type, it is stored in the EAX register (we only consider 32-bit platform);

(2) If the return value is floating point type, it is stored in the x87 stack top register;

(3) The return value cannot be an array type, as required by the syntax of C. If the return value is a struct object of 1, 2, or 4 bytes, it is stored in the register eax, and if 8 bytes, it is stored in [Edx:eax]. If the return value is a struct object of a different size, the C compiler adds a struct pointer to the function as the 1th parameter, as shown below.

typedef struct data{

int num[8]; Total 32 bytes

} DT;

DT = GetData ();

After being processed by the C compiler, the function calls that are actually executed are:

GetData (&DT);

Therefore, we can follow the steps below to translate the intermediate instruction in the form such as "<call, RetVal, func, [Arg1,arg2, ...,argn]>", corresponding to the C function call equivalent to "RetVal =func (arg1, ..., argn);".

(1) The parameters from right to left, that is, from argn to arg1 in turn into the stack;

(2) for {Eax,ecx,edx} These registers to carry out the necessary write-back operation;

(3) When retval is a struct object, and the size is not {1,2,4,8}, we need to take the address of retval and put the address into the stack;

(4) If Func is a function name Myadd, it produces a assembly instruction that is shaped like "call Myadd", and if Func is a pointer to fptr, it produces a assembly instruction shaped like "call * fptr".

(5) According to the sum of memory in the stack parameters, adjust register ESP, that is, generate the assembly instructions such as "Addl Stksize,esp", where stksize represents the total amount of stack memory occupied by all parameters.

(6) Gets the return value from the corresponding register based on the type of the return value. For struct objects with size not {1,2,4,8}, it is not necessary to take the return value from the keynote function. Due to the shape such as "dt = GetData ();" function call to "GetData (&DT)", we can assign a pointer to the structure object dt in the internal function.

For example, for a function call Myadd in a C program, the UCC compiler generates the assembly code as follows:

int myadd (int a,int b);

result = Myadd (num1,num2);

Corresponding assembly code////////////

PUSHL num2//parameter num2 into the stack

PUSHL NUM1//parameter num1 into the stack

Call Myadd//function calls

Addl $8,%ESP//All parameters out of the stack

MOVL%eax, result//Fetch return value

On that basis, let's take a look at the function emitcall,6.3.9 used to generate these assembly code as shown.

Line 7th to 12th puts the arguments from right to left into the stack, and line 13th to 15th calls the Spillreg function to write the necessary writeback for registers eax, ECX, and edx. When the return value is a struct object of size not {1,2,4,8}, we take the address of "return value receive object RetVal" in line 19th, and then the address is placed on the stack at the 20th row. The 23rd line is used to generate a function call instruction, such as "called Myadd" or "Calls * fptr", and the 25th to 28th row to stack all the parameters.


Figure 6.3.9 Emitcall ()

When the return value is a floating-point number, if the keynote function does not need the return value, we will send the x87 stack in line 31st

To prevent the x87 coprocessor's register stack from filling up. If the keynote function requires a floating-point return value, the return value is removed from the x87 stack top register via line 35th to 39th and the x87 stack top register pops up. The 40th to 55th line is used to get "integer return value" or "struct return value of size {1,2,4,8}" from register EAX or edx.

Next, we analyze the function pushargument called in line 9th of 16.3.9, which is shown in the code 6.3.10 line 1th to 24th. Line 3rd to 5th presses into the float type parameter, and line 6th to 8th presses the parameter of type double, line 9th to 20th is used to copy the struct object to the stack, opds[1] of the 17th Row records the number of bytes to be copied ty->size, 18th line opds[2] Is the size of the memory reserved for the struct object in the stack, opds[2] to be greater than or equal to opds[1]. Line 21st to 22nd puts a 4-byte integer into the stack.


Figure 6.3.10 Pushargument ()

In the 26th line of Figure 6.3.10, we give the shape as "*ptr = number;" , UCC calls this command indirectmove, we will load PTR into the register on line 35th, we might set it to eax, and then change the middle instruction of "<IMOV,ptr,number,NULL>" in line 36 to 37 to " <mov, (%eax),number,null> ", and then through the 19th line of the Emitmove function, we can be" *ptr = number; " The following assembly code has been generated, and we have analyzed the Emitmove function in the previous section, which is not repeated here.

Movl num,%ecx

Movl%ecx, (%EAX)

Similarly, the Emitderef function of line 48th to 58th of Figure 6.3.10 is used to deal with the intermediate instruction of the form "T2: *ptr", the corresponding four-tuple is <deref,t2, PTR, null> we first load PTR into the register on line 51st, It may be set as EAX, the 52nd to 53rd line to the intermediate command "<deref, T2, PTR, null>" to "<mov,t2, (%eax),null>", and then through the 55th row of Emitmove function generated the following assembly code:

MOVL (%eax),%ecx;//temporary variable t2 corresponding Register is ECX

When a return statement is encountered in a C program, the UCC compiler produces the following intermediate code:

return retVal;

corresponding Intermediate code////////////

<ret, RetVal, null,null>//Intermediate command RET just ready to return the value

<JMP, exitbb,null,null>//Jump to the only exit of the function EXITBB

In the only exit EXITBB of the function, the UCC compiler generates the following assembly code from the Emitepilogue function, which is used to return from the called function to the keynote function.

EXITBB:

MOVL%EBP,%esp

POPL%edi

POPL%esi

POPL%EBX

POPL%EBP

Ret

Therefore, the intermediate instruction "<ret, RetVal, null,null>" The work to be done is simply passing the return value, as shown in the relevant code 6.3.11. When the return value is a floating-point number and the return value is not in the top register of the x87 stack, we call the Putasmcode function on line 9th to load the return value into the x87 stack top register. If the return value is a struct object with a size not {1,2,4,8}, we change the middle instruction of the shape "<RET,retVal,NULL,NULL>" to "<imov,&dt,retval, NULL" through line 31st to 33rd. >, the comments on line 16th to 28th illustrate this, and then we can call the Emitindirectmove function on line 34th to make a copy of the struct object.

Figure 6.3.11 Emitreturn ()

Figure 6.3.11 Line 37th to 55th is used to transfer "integer return value or struct object size {1,2,4,8}" to "register EAX or edx".

C Compiler anatomy _6.3.4 assembly code Generation _ generate assembly code for function call and return

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.