Compilers 2008 Topic 6: Code Generation 6.5 Functions Code Generation Functions The Call Stack • • • • • • Apart from addressable memory and registers, assembler makes use of a stack to hold information about procedure/function calling and nesting in order to switch to the context of the called function and restore to the caller function when the calling finishes. Before calling the function, parameters are pushed onto the stack. Then, the program address to return to is pushed on the stack. On entering the routine, space is allocated for local variables of that routine. On leaving the routine, the part of the stack used by the routine can be ‘popped’. Recursive routines thus have separate memory space. 2 1 Code Generation Functions The Call Stack • Uses the highest part of free memory • Starts from highest address, and each subsequent element is below • Elements consume different number of bytes (2, 4, 8) • SP: stack pointer: a special register, points to the current top element on the stack. • BP: Base Pointer: a special register, points to the start of the stack space for THIS routine. b a 999-1000 997-998 return address 995-996 BP old_bp i 993-994 991-992 j k 989-990 987-988 r 983-986 SP Free Memory 3 Code Generation Functions Generating Assmebler for functions • For the compiler to generate code for functions, we need to consider the following questions: 1. How are the arguments to the function passed to the invoked function? 2. How are the results of the function call returned to the main program? 4 2 Code Generation Functions Passing of Arguments 1. How are the arguments to the function passed to the invoked function? • Answer: • • The calling code pushes the function's parameters onto the stack, one after another, in reverse order (the first argument specified to the function is pushed last). The caller then executes a CALL instruction to pass control to the function. 5 Source program: ... rutina(a, b) ... int rutina (int a, char *b) { int i, j, k; double r; ... } Object program: rutina: PUSH b PUSH a CALL rutina ‘rutina’ can now access its parameters on the stack. 6 3 Code Generation Functions Functions and the Stack • • • • On entering a subroutine, the subroutine usually resets the base pointer (BP) to point at the start of the local variable space for the subroutine. The old value of BP is first pushed onto the stack. The BP is then set to the current top of the stack (so the old BP is the first element on the stack). When we return from the routine, we restore the old value of BP. 7 Source program: ... rutina(a, b) ... int rutina (int a, char *b) { int i, j, k; double r; ... } Object program: PUSH b PUSH a CALL rutina rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET 8 4 BP, SP PUSH b PUSH a CALL rutina ADD SP,4 Free Memory Initially, Stack is empty … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET 9 PUSH b PUSH a CALL rutina ADD SP,4 … BP SP b Free Memory Param b is pushed onto stack (last param first) rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET 10 5 BP PUSH b PUSH a CALL rutina ADD SP,4 … SP b a Free Memory Param a is pushed onto stack, stack pointer increments. rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET 11 BP PUSH b PUSH a CALL rutina ADD SP,4 … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET SP Function call has side effect of pushing return address onto stack. b a return address Free Memory 12 6 BP PUSH b PUSH a CALL rutina ADD SP,4 b a return address SP … Control passes to rutina. rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET First thing the function must do is preserve the Base Pointer of the main routine. old_bp Free Memory 13 PUSH b PUSH a CALL rutina ADD SP,4 … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET b a return address BP,SP Second thing is to set the BP for the current routine to the current stack pointer value. old_bp Free Memory 14 7 PUSH b PUSH a CALL rutina ADD SP,4 … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET b a return address BP We now advance the stack pointer to leave space for the local variables: i, j, k (int: 2 bytes each) old_bp i j k r SP Free Memory r (double: 8 bytes) 15 PUSH b PUSH a CALL rutina ADD SP,4 … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET b a [BP+8] [BP+6] return address [BP+2] BP Note that the stack grows DOWN from higher addresses to lower, not UP. old_bp i [BP] [BP-2] j k [BP-4] r [BP-14] [BP-6] SP Free Memory 16 8 PUSH b PUSH a CALL rutina ADD SP,4 Set SP to the current BP (the bottom of the top scope is the top of BP, SP the previous scope) … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET b a [BP+8] [BP+6] return address [BP+2] old_bp i [BP] [BP-2] j k [BP-4] r [BP-14] [BP-6] Free Memory 17 PUSH b PUSH a CALL rutina ADD SP,4 … rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET BP Then ‘pop’ the current top of stack into the BP register This Restores the old BP. It also increases SP SP b a [BP+8] [BP+6] return address [BP+2] old_bp i [BP] [BP-2] j k [BP-4] r [BP-14] [BP-6] Free Memory 18 9 PUSH b PUSH a CALL rutina ADD SP,4 … BP The ‘RET’ operation reads the return address from the top of the stack and executes code from that point. SP b a [BP+6] return address [BP+2] old_bp i rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET [BP+8] [BP] [BP-2] j k [BP-4] r [BP-14] [BP-6] Free Memory 19 PUSH b PUSH a CALL rutina ADD SP,4 BP, SP This ‘ADD’ operation takes ‘a’ and ‘b’ off the stack (2 bytes each) b a [BP+8] [BP+6] [BP+2] [BP] [BP-2] … [BP-4] [BP-6] rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV SP,BP POP BP RET [BP-14] 20 10 Code Generation Functions Returning Value 2. How are the results of the function call returned to the main program? • Answer: • Depends on the compiler, but conventionally: • • if the result fits in the EAX register, leave the result there. Otherwise, place the values on the stack, or in memory. 21 Source Program: ... rutina(a, b) ... int rutina (int a, char *b) { int i, j, k; double r; ... return k; } Object Program: PUSH b PUSH a CALL rutina ADD SP,4 rutina: PUSH BP MOV BP,SP SUB SP,14 ... MOV EAX, [BP-6] MOV SP,BP POP BP RET Move K into EAX 22 11