Procedure Call in MIPS(3)
- jal(jump and link) [location]: 다음에 실행될 명령어(PC+4)를 $ra에 저장하고 location으로 jump
- jr(jump register) [location]: location으로 jump
1. A) jal loc: loc으로 이동하고, PC+4(jal loc 다음 instruction의 주소)를 $ra에 저장
2. B) sub $sp, 4: stack pointer 4 감소시켜 스택에 4바이트 공간 할당
3. B) sw $ra, 0($sp): $ra의 주소(caller의 return address)를 $sp에 저장 → save 책임이 callee에게 있음
4. B) jal loc2: loc2로 이동하고, PC+4(jal loc2 다음 instruction의 주소)를 $ra에 저장
...
5. C) jr $ra: $ra로 jump → jal loc2 다음의 instruction으로 이동(4)
6. B) lw $ra, 0($sp): $sp에 저장된 값을 $ra에 저장(A에서 jal을 호출한 지점의 다음 instruction 주소가 $ra에 저장)
7. B) add $sp, 4: stack pointer를 4 증가시켜 스택 공간 복원
8. B) jr $ra: $ra에 저장된 주소(A에서 B를 호출한 지점 다음 주소)로 jump
Stack Frame
함수가 호출될 때마다 그 함수와 관련된 일련의 정보들을 스택에 쌓아 놓게 되는데, 이를 함수의 Stack Frame이라 한다.
- Stack Frame
- procedure가 사용 중인 데이터를 stack 상 자신의 frame에 저장한다.
- frame pointer($fp)를 기본 위치로 하여 procedure가 그 데이터에 접근한다.
- stack은 expression evalutaion의 용도로도 사용되므로, $sp는 procedure 사용 중에도 값이 변할 수 있다.
※ frame pointer: stack frame의 시작 위치를 가리키는 포인터
※ stack pointer: stack의 top을 가리키는 포인터
- Stack Frame에 저장되는 내용
- 전달되는 argument 중 5번째 argument부터 stack frame에 저장된다(4개까지는 a0~a3 레지스터에 저장)
- save된 레지스터들의 값
- 해당 procedure의 지역 변수들
레지스터의 저장
- 변수들을 최대한 레지스터에 mapping하여 사용
- 레지스터는 메모리보다 10배 이상 빠름
- procedure 호출 시 레지스터를 새로운 지역 변수에 mapping하여 사용
- procedure 호출 시 레지스터의 기존 내용 저장 필요
- callee save 또는 caller save
<MIPS의 경우>
- callee-save register: saved($0~7), frame pointer $fp
- caller-save register: temporary($t0~9), argument($a0~3), return value($v0~1), return address($ra)
Procedure Call Actions
Caller
- caller-save 레지스터들 중 사용 중인 것을 스택에 저장
- 전달할 argument의 set up(앞의 4개는 $a0~3)에, 나머지는 stack에 저장
- jal instruction을 이용하여 callee 호출(jal 실행 시 return address는 $ra에 자동 저장)
Callee
- frame 크기를 계산하여 스택에 그 크기만큼의 공간 할당($sp←$sp - frame size)
- callee-save register 중 사용할 레지스터를 스택에 저장($s0~7, $fp-현재 stack frame의 frame pointer를 가리켜야 하므로 저장)
- $fp 값을 현재 stack frame의 시작 위치로 결정
Callee returns
- return value가 있는 경우, $v0~1에 그 값을 저장
- 저장했던 callee-save 레지스터 값을 복원($s0~7, $fp)
- 스택에서 이 procedure의 frame을 비움( $sp←$sp + frame size)
- jump $ra를 이용하여 return