procedure?
In computer programming, a subroutine is a sequence of program instructions that perform a specific task, packaged as a unit. In different programming languages a subroutine may be called a procedure, a function, a routine, a method, or a subprogram.
'특정 작업을 수행하기 위한 instruction들의 연속'
프로시저(procedure)나 함수는 이해하기 쉽고 재사용이 가능하도록 프로그램을 구조화하는 방법 중 하나이다.
인수(parameter)는 프로시저에 값을 보내고 결과를 받아오는 일을 하므로,
프로그램의 다른 부분 및 데이터와 프로시저 사이의 인터페이스 역할을 한다.
- 프로시저 = 스파이
스파이는 비밀 계획을 가지고 출발해서, 필요한 자원 획득하여 임무 완수하고, 흔적을 없앤 후 원하는 결과를 가지고 출발 장소로 되돌아온다.
지정된 임무 수행하는 것 외에 다른 것은 아무것도 건드리지 말아야 한다.
Steps
Register Usage
link : 프로시저 종료 후 올바른 주소로 되돌아올 수 있도록 호출한 곳과 프로시저 사이에 링크를 형성한다.
프로그램 카운터(Program counter, PC) : 실행 중인 명령어의 주소를 가지고 있는 레지스터
int leaf_example (int g, h, i, j) {
int f;
f = (g + h) - (i + j);
return f;
}
// Arguments g, ..., j in $a0, ..., $a3
// f in $s0 (hence, need to save $s0 on stack)
// Result in $v0
leaf_example : // 프로시저 레이블
addi $sp, $sp, -4 // 스택에 $s0를 저장할 자리를 만든다
sw $s0, 0($sp) // save $s0 on stack for use afterwards
add $t0, $a0, $a1 // Procedure body
add $t1, $a2, $a3
sub $s0, $t0, $t1 // f = t0 - t1
add $v0, $s0, $zero // return f. f를 결과 값 레지스터에 복사한다.
lw $s0, 0($sp) // restore $s0. 전에 저장해 두었던 값을 스택에서 꺼내 레지스터를 원상 복귀한다
addi $sp, $sp, 4 // adjust stack to delete 1 item
jr $ra // jump back to calling routine
- 스파이는 때로 다른 스파이를 고용하여 일의 일부를 맡기고, 그 스파이는 또 다른 스파이를 고용할 수 있다.
- 이처럼 프로시저도 다른 프로시저를 호출할 수 있고, 심지어는 자기 자신을 호출하는 recursive 프로시저도 있다.
- 여러 프로시저를 호출하면서 생기는 문제를 피하기 위해,
값이 보존되어야 할 모든 레지스터를 스택에 넣는다.- 호출 프로그램은 인수 레지스터(a0 - a3)와 임시 레지스터(t0 - t9) 중
프로시저 호출 후에도 계속 사용해야 하는 것을 모두 스택에 넣는다- 피호출 프로그램은 복귀 레지스터(ra)와 저장 레지스터(s0 - s7) 중
피호출 프로그램이 사용하는 레지스터를 모두 저장한다.- 스택 포인터 $sp는 스택에 저장되는 레지스터 개수에 맞추어 조정된다.
- 복귀 후에는 메모리에서 값을 꺼내 레지스터를 원상 복구하고, 이에 맞추어 스택 포인터를 다시 조정한다.
int fact(int n) {
if (n < 1)
return 1;
else
return n * fact(n - 1);
}
// Argument n in $a0
// Result in $v0
인수(argument) vs 인자( = 매개변수. parameter)
fact :
addi $sp, $sp, -8 // adjust stack for 2 items
sw $ra, 4($sp) // save the return address
sw $a0, 0($sp) // save the argument n
slti $t0, $a0, 1 // test for n < 1 => n < 1이면 t0 = 1
beq $t0, $zero, L1 // t0 == 1이면 (즉, n >= 1이면) go to L1
addi $v0, $zero, 1 // 넘어왔다는 건, n < 1일 때. return 1
addi $sp, $sp, 8 // pop 2 items off stack
jr $ra // return to caller
L1 :
addi $a0, $a0, -1 // argument gets n-1
jal fact // call fact with n-1
lw $a0, 0($sp) // return from jal : restore argument n
lw $ra, 4($sp) // restore the return address
addi $sp, $sp, 8 // adjust stack pointer to pop 2items
mul $v0, $a0, $v0 // return n * fact(n-1)
jr $ra // return to the caller
Sign extend to 32 bits in rt
lb rt, offset(rs)
lh rt, offset(rs)
Zero extend to 32 bits in rt
lbu rt, offset(rs)
lhu rt, offset(rs)
Store just rightmost byte/halfword
sb rt, offset(rs)
sh rt, offset(rs)
void strcpy (char x[], char y[]) {
int i;
i = 0;
while ( (x[i] = y[i]) != '\0' )
i += 1;
}
// addresses of x, y in $a0, $a1
// i in $s0
strcpy :
addi $sp, $sp, -4 // adjust stack for 1 item
sw $s0, 0($sp) // save $s0
add $s0, $zero, $zero // i = 0;
L1 :
add $t1, $s0, $a1 // address of y[i] in $t1
lbu $t2, 0($t1) // $t2 = y[i]
add $t3, $s0, $a0 // address of x[i] in $t3
sb $t2, 0($t3) // exit loop if y[i] == 0
addi $s0, $s0, 1 // i = i + 1
j L1 // next iteration of loop
L2 :
lw $s0, 0($sp) // restore saved $s0
addi $sp, $sp, 4 // pop 1 item from stack
jr $ra // and return