1. Procedure (Function)
$a0 ~ $a3: 4개의 argument register
$v0 ~ $v1: 2개의 value register (to return)
$ra: return address register
jal calls a procedure: 인자들은 $a0 ~ $a3 통해서 전달
jr returns from the procedure: 결과는 $v0, $v1에 저장
jal ProcedureAddress // jump and link
$ra <- pc+4 (callee 끝나면 pc+4로 돌아오도록)
#pc <- jump target
jal은 $ra (return address reguster)에 돌아올 주소를 저장해둔다 (pc+4)
jr $ra // return (pc <- $ra), jump to address in $ra
2. The Stack - Spilling registers (임시 보관)
caller에서 사용하는 레지스터를 callee가 맘대로 사용하는 문제 발생
-> spilling (임시 보관)이 필요함!
-> callee에게 모든 책임을 전가하는 해결 방법
cpu는 32개의 제한된 레지스터를 갖고 있음
-> 코드에서 사용하는 모든 변수를 저장할 수 없음
-> 그래서 'stack'을 사용하여 레지스터를 백업, 저장한다
stack은 메모리 공간 중에 데이터를 임시적으로 저장해두는 곳!
- LIFO (Last In First Out)
- $sp($29)는 stack의 top을 가리키기 위해 사용됨
- 스택은 '높은 주소'에서 '낮은 주소'로 자란다
- push: add data onto the stack ($sp = $sp-4) ↓
- pop: remove data from the stack ($sp = $sp+4) ↑
3. Preserved and NonPreserved Registers
stack을 사용하는 방법은 만약 temporary registr를 사용하지 않는다면 자원 낭비됨
-> 낭비를 줄이기 위해 MIPS는 preserved, nonpreserved 레지스터를 구분한다
• preserved: $s0 ~ $s7 (saved, 사용 시 callee의 책임)
• non-preserved: $t0 ~ $t9 (temporary, 사용 시 caller의 책임)
-> callee가 맘대로 써도 됨
callee가 preserved 쓸 땐 항상 save, restore 필수!
하지만 non-preserved는 맘대로 써도 된다