보관/시스템 소프트웨어

Procedure Call in MIPS(3)

unhyepnhj 2024. 10. 16. 21:56

  • 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