2016-03-30
MIPS 함수 호출과 스택 사용
jal label // 함수 호출에 사용
jr $ra // 함수 리턴에 주로 사용
$ra에 함수 호출자(caller)의 return address가 저장됨
함수 인자는 $a0 ~ $a3에 저장
jal 명령으로 함수 호출
함수 내용 실행
함수 결과값 $v0 ~ $v1에 저장
jr $ra 로 함수 리턴
(하지만 이것만 갖고는 안된다)
leaf function 말단 함수의 경우 꼭 $ra등 저장하지 않아도 됨
non-leaf function인 경우 함수 호출시 잃게 되는 정보 중 함수 호출 후에도 필요한 것들을 스택에 저장
$ra 는 반드시 저장, $s0 ~ $s7 중 사용하는 것을 저장,
그 외 다른 레지스터나 다른 값도 필요에 따라 저장
호출받은 함수(callee)입장에서 함수 진입과 동시에 수행
스택 저장 예시 ($ra 하나만 저장할 때)
addi $sp, $sp, -4 sw $ra 0($sp) # 다른 함수 호출 등 함수 내용 실행 lw $ra 0($sp) addi $sp, $sp, 4 jr $ra
lw $t0, x($gp)
la $t1, x lw $t0, 0($t0)
int add(int x, int y) { // leaf function
return x + y; // 말단 함수
}
int twice(int x) { // non-leaf function
return add(x, x); // 다른 함수를 부르는 함수
}
int main(void) {
int n = twice(8);
printf("%d", n);
return 0;
}
int add(int x, int y) {
return x + y;
}
int twice(int x) {
return add(x, x);
}
int main(void) {
int n = twice(8);
printf("%d", n);
return 0;
}
<잘못된 버전>
add:
add $v0,$a0,$a1
jr $ra
twice:
move $a1, $a0
jal add
jr $ra
main:
li $a0, 8
jal twice
# 출력 시스템 콜
jr $ra
int add(int x, int y) {
return x + y;
}
int twice(int x) {
return add(x, x);
}
int main(void) {
int n = twice(8);
printf("%d", n);
return 0;
}
add:
add $v0,$a0,$a1
jr $ra
twice:
addi $sp, $sp, -4
sw $ra, 0($sp)
move $a1, $a0
jal add
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
main:
addi $sp, $sp, -4
sw $ra, 0($sp)
li $a0, 8
jal twice
# 출력 시스템 콜
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra