프로시저 호출 단계
- 레지스터에 매개변수 배치
- 제어권을 프로시저에게 줌
- 프로시저(callee)를 위한 저장공간 확보
- 프로시저의 작업 수행
- caller를 위한 레지스터 결과 배치
- 호출 장소로 돌아가기
레지스터
$v0~1 | 결과값 64비트일수도 있기때문에 2개 존재 |
(레지스터 2~3) |
$a0~3 | 아규먼트 | (레지스터 4~7) |
$t0~9 | 임시값 callee가 덮어쓸수 있다. |
(레지스터 8~15) |
$s0~7 | saved callee에 의해 저장/복원 |
(레지스터 16~23) |
$gp | 정적 데이터를 위한 글로벌 포인터 | (레지스터 28) |
$sp | 스택 포인터 | (레지스터 29) |
$fp | 프레임 포인터 | (레지스터 30) |
$ra | 리턴 주소 | (레지스터 31) |
프로시저 호출 명령어
- 프로시저 호출: jump & link
jal ProcedureLabel
- 1. $ra에 다음 명령어의 주소를 넣는다.
- 2. 타겟 주소로 점프
- 프로시저 리턴: jump register
jr $ra
- 1. $ra에 프로그램 카운터를 복사한다.
- 2. 계산된 점프에도 사용할 수 있다.
- 예를 들어, Case/Switch 명령문
말단/비말단 프로시저
- caller : 상수를 호출하는 부분
- callee : 상수를 호출 당하는 부분
- 스택에 $s0~1와 같은 saved 레지스터 값을 저장했다가 복구한다.
말단(Leaf) 프로시저
- 말단 프로시저(Leaf Procedures) : 함수가 더이상 다른 함수를 호출하지 않는 경우
말단(Leaf) 프로시저 예제
- C 코드
int leaf_example (int g, h, i, j) {
int f;
f = (g + h) - (i + j);
return f;
}
- 아규먼트 g, h, i, j : $a0, $a1, $a2, $a3
- f : $s0 (따라서 스택에 $s0를 저장)
- 결과 : $v0
- MIPS 코드
leaf_example:
addi $sp, $sp, -4 # callee가 overwrite하지 않도록
sw $s0, 0($sp) # 스택에 기존 변수 $s0을 저장
add $t0, $a0, $a1 # 프로시저 바디
add $t1, $a2, $a3 # 프로시저 바디
sub $s0, $t0, $t1 # 프로시저 바디
add $v0, $s0, $zero # 결과
lw $s0, 0($sp) # 스택의 $s0를 불러오고
addi $sp, $sp, 4 # 스택 오프셋 조정
jr $ra # 리턴하여 다음 명령어 수행
비말단(Non-Leaf) 프로시저
- 비말단 프로시저(Non-Leaf Procedures) : 다른 프로시저를 호출하는 프로시저
- 중첩 호출의 경우 caller는 스택에 저장
- 리턴 주소
- 호출 후 필요한 모든 인수 및 임시값
- 호출 후 스택에서 복원
비말단(Non-Leaf) 프로시저 예제
- C 코드
- 팩토리얼 재귀함수
int fact (int n) {
if (n < 1) return 1;
else return n * fact(n - 1);
}
- 인수 n : $a0
- 결과값 : $v0
- MIPS 코드
fact:
addi $sp, $sp, -8 # callee가 overwrite하지 않도록
sw $ra, 4($sp) # 스택에 $ra 저장
sw $a0, 0($sp) # 스택에 $a0 저장
slti $t0, $a0, 1 # 만약 n<1 참이면 $t0 = 1, 거짓이면 $t0 = 0
beq $t0, $zero, L1 # 거짓이면 L1으로 이동
addi $v0, $zero, 1 # 참이면 $v0 = 1
addi $sp, $sp, 8 # 스택 오프셋 복원
jr $ra # 리턴
L1:
addi $a0, $a0, -1 # n을 감소시켜
jal fact # fact(n-1) 재귀 함수 호출
lw $a0, 0($sp) # 스택에 저장했던 원래 n값($a0) 불러오기
lw $ra, 4($sp) # 스택에 저장했던 원래 리턴주소($ra) 불러오기
addi $sp, $sp, 8 # 스택 오프셋 복원
mul $v0, $a0, $v0 # $v0 = n * $v0
jr $ra # 리턴
스택의 로컬 데이터
- callee가 할당한 로컬 데이터
- 예: C 자동 변수
- 프로시저 프레임(활성화 레코드)
- 일부 컴파일러에서 스택 저장소를 관리하는 데 사용
메모리 레이아웃
- 텍스트(Text) : 프로그램 코드
- 정적 데이터(Static data) : 전역 변수
- C의 정적 변수 : 상수 배열, 문자열
- $gp는 이 세그먼트에 ±오프셋을 허용하는 주소로 초기화
- 동적 데이터(Dynamic data) : 힙
- C : malloc, Java : new
- 스택(Stack) : 자동 저장
- 스택이랑 힙이랑 만났을때 스택오버플로우 발생
'컴퓨터시스템구조' 카테고리의 다른 글
[컴퓨터시스템구조] 11. MIPS 주소지정 (0) | 2023.10.14 |
---|---|
[컴퓨터시스템구조] 10. MIPS 문자열 연산자(lb, lh, sb, sh) (0) | 2023.10.14 |
[컴퓨터시스템구조] 08. MIPS 조건부 연산자(beq, bne, j, slt) (0) | 2023.10.14 |
[컴퓨터시스템구조] 07. MIPS 논리 연산자(sll, srl, and, or, nor) (0) | 2023.10.14 |
[컴퓨터시스템구조] 06. MIPS 포맷(R-포맷, I-포맷) (1) | 2023.10.14 |