함수 호출 작동 방식

Program counter (명령어 포인터): 다음에 실행될 명령어의 주소를 가진 레지스터

프로시저(함수)를 실행하는 6단계 (중요)

caller: 함수를 부르는 함수

callee: 불려지는 함수

  1. Caller가 Callee가 접근 할 수 있는 곳에 파라미터를 배치. MIPS에서는 $a0 ~ $a3(32bit)까지가 파라미터(arguments) 레지스터
  2. Caller가 Callee에게 컨트롤을 넘김 (Callee가 실행 됨)
  3. Callee가 실행되기 위해 필요한 스토리지 공간(메모리)을 할당 받음. 보통은 스택 공간에 할당
  4. Callee가 작업을 수행
  5. Callee가 Caller가 접근 할 수 있는 곳에 result를 배치. MIPS에서는 $v0 ~ $v1까지가 value 레지스터
  6. Caller가 Callee에게 컨트롤을 넘김. 이때 $ra (return address) 레지스터를 사용해 원래 실행되던 위치로 돌아감.

프로시저 콜 명령어

Procedure call (프로시저 콜): jump and link

jal ProcedureLabel

해당 명령어가 실행되고 난 후 ProcedureLabel에 있는 명령어로 바로 이동

다음에 실행 할 명령어의 주소를 $ra 레지스터에 저장

Procedure return (프로시저 리턴): jump register

jr $ra

$ra에 있는 값을 program counter에 복사

Leaf Procedure

의미: 내부에서 자기를 포함한 다른 함수를 호출하지 않는 함수

ex)

int leaf_example (int g, h, i, j) {
	int f;
	f = (g+h) - (i+j);
	return f;
}

파라미터는 $a0..$s3

f는 $s0

결과는 $v0

이를 어셈블리로 변환하면

leaf_example:
	addi $sp, $sp, -4
	sw   $s0, 0($sp)      #스택에 $s0값 저장
	add  $to, $s0, $a1    # g+h
	add  $t1, $a2, $a3    # i+j
	sub  $s0, $t0, $t1
	add  $v0, $s0, $zero  #결과값
	lw   $s0, 0($sp)      # 스택에 저장되있던 $s0값을 가져옴
	addi $sp, $sp, 4      # 함수가 종료되었으므로 할당받은 스택 영역을 해제
	jr   $ra              #리턴 

Non-Leaf Procedure

의미: 함수 내부에서 자신을 포함한 다른 함수를 호출하는 함수

중첩 호출이기에 caller는 스택에 필요한 정보를 저장해야 함

  • 돌아올 주소 ($ra에 들어있는 값)
  • 호출한 후 필요한 파라미터와 임시 값들

ex)

int fact(int n) {
	if (n < 1) return 1;
	else return n * fact(n-1);
}

파라미터 n은 $a0

result는 $v0

어셈블리로 변환하면

fact:
	addi $sp, $sp, -8
	sw   $ra, 4($sp)
	sw   $a0, 0($sp)
	slti $t0, $a0, 1      # n < 1이면 1, 아니면 0
	beq  $t0, $zero, L1   # t0이 0이면 L1으로 이동
	addi $v0, $zero, 1
	addi $sp, $sp, 8
	jr   $ra
L1: 
	addi $a0, $a0 -1
	jal  fact
	lw   $a0, 0($sp)
	lw   $ra, 4($sp)
	addi $sp, $sp, 8
	mul  $v0, $a0, $v0
	jr   $ra

여기서 첫줄에 스택 영역에 8바이트의 공간을 할당한다. 그 이유는 다른 함수를 내부적으로 호출 할 때, 다시 돌아와야 할 주소(32비트)와 파라미터 (int타입이므로 4바이트)를 저장해야 하므로 총 8바이트를 할당하게 된다.

로컬 데이터가 스택에 쌓이는 과정

Procedure frame (activation record)

함수를 실행 할 시, 스택에서는 해당 함수를 공간이 frame이 만들어 짐. 이때 레지스터에 현재 실행중인 프레임의 시작 주소가 저장되는데, 이것을 프레임 포인트($fp)라고 한다.

프레임 데이터 저장 순서

아래로 갈 수록 낮은 주소값을 가진다.

  • Saved argument registers (저장된 파라미터 값)
  • Saved return address (리턴 주소)
  • Saved saved registers (이건 뭔지 모르겠음..)
  • Local arrays and structures (로컬 데이터)

'컴퓨터 구조' 카테고리의 다른 글

Static Linking 부터 로드까지  (0) 2023.06.30
명령어 addressing  (0) 2023.06.30
ISA, ABI, 명령어의 구조  (0) 2023.06.28
스택 포인터  (0) 2023.06.27
MIPS프로세서 명령어의 구조  (0) 2023.06.11