Procedure Call & Return

프로시저 콜 & 리턴

  • procedure caller는 callee가 접근 가능한 argument register들에 함수의 파라미터들을 저장한다.

  • callee 주소로 jump and link하여 callee 명령어를 수행하고 수행이 완료되면 돌아올 주소값을 $ra에 저장한다. 이 때 jal 명령은 $ra에 관련된 값을 덮어쓰므로, jal 명령어를 호출하기 전 $ra의 값을 메모리 등 다른 곳에 저장해야 한다.

  • 이 때 callee는 stack frame을 할당받아 로컬 변수를 저장한다.

stack

  • argument register, return address register의 경우 프로시저 내에서 또다른 프로시저, 함수를 콜 할 때마다 덮어쓰이기 때문에 stack에 저장해두고 하위 작업이 완료되면 다시 register에 불러와서 사용한다.

  • stack은 높은 주소값에서부터 낮은 주소값으로 자라난다.

  • stack pointer: 가장 최근에 스택으로 할당된 주소값에 대한 포인터

  • frame pointer: top stack frame의 맨 아래(가장 높은) 주소값에 대한 포인터

MIPS Register Convention

  • MIPS에서는 각 Register의 역할을 정의해두고 있다.

factorial 예제

  • factorial을 구하는 간단한 c 코드를 어셈블리어를 사용하여 직접 구현할 수 있다.

int fact (int n) {
    if (n < 1) 
        return (1);
    else
        return (n * fact(n1));
}
fact:
    addi $sp, $sp, -8 // 스택 포인터를 이동시켜 스택에 기존 레지스터 값을 저장해둔다.
    sw $ra, 4($sp)
    sw $a0 0($sp)
    
slti $t0, $a0, 1 // 2보다 작을 경우 $t0 에 1을 대입한다
    
beq $t0, $zero, L1
    
addi $v0, $zero, 1 // $v0이 최종 결과가 될 레지스터이며 해당 값에 1을 넣는다.
    
jr $ra

L1:

    addi $sp, $sp,
8
    
sw $ra, 4($sp)
    
sw $a0, 0($sp)

    addi $a0, $a0,
1

    jal fact

    lw $a0, 0($sp) // 스택 데이터를 레지스터에 복원한다.
    
lw $ra, 4($sp)

    addi $sp, $sp, 8

    mul $v0, $a0, $v0 // 최종 결과 값에 현재 $a0을 곱한다. 여기가 재귀적으로 호출되면서 팩토리얼 결과가 계산된다.
    
jr $ra

Last updated