200 likes | 424 Views
Procedure Entry / Exit. 권신일 99390274 조재호 2000160239 이한욱 2005220146. Procedure Call Convention. register-use convention Also called procedure call convention . A software protocol governing the use of registers by procedures .
E N D
Procedure Entry / Exit 권신일 99390274 조재호 2000160239 이한욱 2005220146
Procedure Call Convention • register-use convention Also called procedure call convention. A software protocol governing the use of registers by procedures. • The MIPS CPU contains 32 general-purpose registers that are numbered 0–31. • Register $0 always contains the hardwired value 0.
MIPS registers ■ Registers $at (1), $k0 (26), and $k1 (27) are reserved for the assembler and operating system and should not be used by user programs or compilers. ■ Registers $a0–$a3 (4–7) are used to pass the first four arguments to routines (remaining arguments are passed on the stack). Registers $v0 and $v1 (2, 3) are used to return values from functions. ■ Registers $t0–$t9 (8–15, 24, 25) are caller-saved registers that are used to hold temporary quantities that need not be preserved across calls (see Section 2.7 in Chapter 2) ■ Registers $s0–$s7 (16–23) are callee-saved registers that hold long-lived values that should be preserved across calls. ■ Register $gp (28) is a global pointer that points to the middle of a 64K block of memory in the static data segment. ■ Register $sp (29) is the stack pointer, which points to the last location on the stack. Register $fp (30) is the frame pointer. The jal instruction writes register $ra (31), the return address from a procedure call. These two registers are explained in the next section.
Procedure Calls • procedure call frame • To hold values passed to a procedure as arguments • To save registers that a procedure may modify, but which the procedure’s caller does not want changed • To provide space for variables local to a procedure
Layout of a stack frame • The frame pointer ($fp) points to the first word in the • currently executing procedure’s stack frame. The stack pointer ($sp) points to the last word of frame. The • first four arguments are passed in registers, so the fifth argument is the first one stored on the stack.
Stack • last in first out data structure • push: puts an item into the stack • pop: gets the item at the top of the stack • stack pointer (SP) in most architecture • why? because stack is used so frequently • MIPS stack • push sub $sp, $sp, 4 sw $t0, ($sp) • pop lw$t0, ($sp) add $sp, $sp, 4 old high addr … … … $sp new low addr
jal loc $ra loc: sub $sp, 4 sw $ra, ($sp) loc2: … jal loc2 $ra … … lw $ra, ($sp) add $sp, 4 jr $ra … jr $ra MIPS Procedure Call caller callee & caller … another callee … … … … … … … … … … …
Stack Frame argument 5 old $fp argument 6 …. SF of procedue A saved registers offset from $fp SF of procedue B local variables SF of procedue C new $fp stack grows and shrinks during expression evaluation $sp stack
SF of procedure C main program starts main calls procedure A Proc A calls procedure B Proc B calls procedure C SF of main SF of procedure A SF of procedure B Stack Frames for Procedure Calls stack
Stack Frames for Procedure Calls stack main program starts SF of main main calls procedure A SF of procedure A Procedure A finishes Proc A calls procedure B Procedure B finishes SF of procedure B SF of procedure C Procedure C finishes
procedure call convention • procEntryExit1 • immediately before the caller invokes the callee • procEntryExit2 • just as the callee starts executing • procEntryExit3 • and immediately before the calleereturns to the caller
procEntryExit1 • 1. Pass arguments. By convention, the first four arguments are passed in registers $a0–$a3. Any remaining arguments are pushed on the stack and appear at the beginning of the called procedure’s stack frame. • 2. Save caller-saved registers. The called procedure can use these registers ($a0–$a3 and $t0–$t9) without first saving their value. If the caller expects to use one of these registers after a call, it must save its value before the call. • 3. Execute a jal instruction (see Section 2.7 of Chapter 2), which jumps to the callee’s first instruction and saves the return address in register $ra.
procEntryExit2 • 1. Allocate memory for the frame by subtracting the frame’s size from the stack pointer. • 2. Save callee-saved registers in the frame. A callee must save the values in these registers ($s0–$s7, $fp, and $ra) before altering them since the caller expects to find these registers unchanged after the call. Register $fpis saved by every procedure that allocates a new stack frame. However, register $ra only needs to be saved if the callee itself makes a call. The other calleesaved registers that are used also must be saved. • 3. Establish the frame pointer by adding the stack frame’s size minus 4 to $sp and storing the sum in register $fp.
procEntryExit3 • 1. If the callee is a function that returns a value, place the returned value in register $v0. • 2. Restore all callee-saved registers that were saved upon procedure entry. • 3. Pop the stack frame by adding the frame size to $sp. • 4. Return by jumping to the address in register $ra.
Package Frame Public abstract class Frame implements Temp.TempMap { Abstract public Temp RV(); Abstract public Temp FP(); Abstract public Temp.TempList registers(); Abstract public string tempMap(Temp temp); Abstract public intwordSize(); Abstract public Tree.ExpexternalCall(String func, Tree.ExpListargs); Abstract public Frame newFrame(Temp.Label name, Util.BoolList formals); Public AccessList formals; Public Temp.Label name; Abstract public Access allocLocal(boolean escape); Abstract public Tree.Stm procEntryExit1(Tree.Stm body); Abstract public Assem.InstrList procEntryExit2(Assem.InstrList body); Abstract public Tree.Stm procEntryExit3(Tree.Stm body); Abstract public Assem.InstrListcodgen(Tree.Stmstm); }
FP(), RV(), registers(), tempMap(Temp temp),wordSize() // Temp 타입의 레지스터를 assem에서 사용가능한 실제 레지스터 이름으로 변환 // tempMap(ZERO) => “$0” public String tempMap(Temp temp) { … } public intwordSize() { return wordSize; } private static final intwordSize = 4; // 프레임 포인터 리턴 public Temp FP() { return FP; } // 리턴값 리턴 (리턴값은vo에 저장) public Temp RV() { return V0; } // 레지스터 목록. Temp 타입으로 관리. public Temp[] registers() { return registers; } private static Temp[] registers = { ZERO, RA, SP, FP, T0, ….. };
externalCall(String s, List<Tree.Exp> args)allocLocal(boolean escape) // 인자값으로 넘길 값을 프레임에 맨 아래에 추가 // 만약 레지스터로 넘길 것이면 레지스터에 저장 public Access allocLocal(boolean escape) { if (escape) { … } else … }
procEntryExit1(Tree.Stm body) procEntryExit2(Assem.InstrListbody)procEntryExit3(Tree.Stm body) // 레지스터중caller 가 저장해야할 레지스터를 저장 및 복원 // 인자 값인 body는 IR트리 // IR트리의진입점에caller save 코드를 추가 public void procEntryExit1(List<Tree.Stm> body) { … } // 레지스터중callee가 저장해야할 레지스터를 저장 // 인자값인body는 assem코드 리스트 // Assem코드의 시작 부분에 callee save 부분 추가 public void procEntryExit2(List<Assem.Instr> body) { … } // callee레지스터의 복원 및 sp값의 복원을 통한 프레임의 수정 // 인자 값인 body는 assem코드 리스트 public void procEntryExit3(List<Assem.Instr> body) { … }