Supporting Procedures in Computer Hardware
Six Steps in Execution of a Procedure
1.
Main routine(caller) 가 parameters(=arguments) 를 procedure(callee)가 접근할 수 있는 곳에 위치시킨다.
a.
caller : 함수를 부르는 루틴
b.
callee: 불러지는 함수
c.
$a0 - $a3이 register에서 arguments를 위한 곳 (four argument registers)
2.
Caller가 callee로 control을 넘긴다. (callee가 실행됨)
3.
Callee가 실행되면 실행하기 위해 필요한 스토리지 공간, 즉 메모리를 할당받는다.(보통 stack이라는 공간)
4.
Callee가 desired task를 수행한다.
5.
Callee는 task끝난 후 결과를 Caller가 접근할 수 있는 곳에 위치시킨다.
a.
$v0 - $v1이 result values를 위한 곳이다( two value registers for result values)
6.
Callee는 Caller에게 컨트롤을 넘긴다. (Caller 실행)
a.
이때는 $ra가 실행 - 리턴해야하는 주소값이 들어가있음.
b.
$ra가 pc(program counter)로 복사되어 6번 단계 실행 수에는 $ra에 담겨있는 명령어부터 수행하게 된다.
Register Usage
28~31 : special register
Procedure Call Instructions
1.
jal procedureLabel
•
procedure call: jump and link 명령어
•
실행시 procedureLabel에 있는 명령어로 이동
•
동시에 현재 그 명령어(procedurelabel) 다음에 있는 명령어를 $ra에 넣는다.
2.
jr $ra
•
procedure return: jump register 명령어
•
$ra 레지스터의 명령어를 Program Counter(PC)에 복사
•
case/switch statements같은 계산된 jump 명령어에서도 사용되기도 한다.
Leaf Procedure Example
•
C code :
int leaf_example (int g, h, i, j)
{ int f;
f = (g+h) - (i+j);
return f;
}
Python
복사
•
arguments g, ..., j는 $a0, ..., $a3 에 있음
•
f 는 $s0에 있음 즉, stack의 $s0에 저장해야한다
•
result는 $v0에 들어있음
1.
stack pointer($sp) 에 4를 빼주는 연산 = stack값이 4만큼 감소 = stack 에 4바이트만큼 메모리 할당
2.
$s0값을 $sp에 복사 왜? s0의 원래의 값을 함수에서 쓰기전에 스택에 넣어뒀다가 다시 복원하기 위해서 즉, s0의 원래값을 보존하기 위해서
3.
$a0와 $a1 더해 $t0에 저장 → g+h
4.
$a2와 $a3 더해 $t1에 저장 → i+j
5.
$t0에서 $t1뺴 $s0에 저장 → (g+h)-(i+j)
6.
리턴값 $v0에 넣기 위해 $s0값을 zero와 더하는 방식으로 $v0에 넣어줌
7.
load word 명령어로 $sp에 저장해두었던 $s0의 원래 값을 복원
8.
sp값 다시 조정 → $sp 에 4 다시 더해줌 : 할당받은 4바이트 할당 해제
9.
$ra의 값을 pc(program counter)로 복사해 caller로 가게해준다. 이 명령어 후에는 caller가 동작
Non-Leaf Procedures
자신을 포함한 다른 procedures들을 호출함
•
procedure내에서 다른 procedure을 호출하는 nested call이기 때문에 caller는 stack에 필요한 것들(return address나 call이후에 필요한 arguments나 temporaries) 저장해야한다.
•
call 이후에는 stack으로부터 복원시켜야 함
Non-Leaf procedure Example
•
C code :
int fact (int n)
{
if (n < 1) return 1;
else return n * fact(n-1);
}
C
복사
argument n in $a0
result in $v0
•
MIPS Code
Lear Procedure보다 복잡한 모습
fact
1.
$sp(stack pointer)에 -8해주는 연산으로 stack memory에 8바이트 할당
2.
store word(sw) 명령어로 $ra레지스터 값을 4($sp) 즉, 스택에 넣는다
3.
store word(sw) 명령어로 $a0레지스터 값을 0($sp) 즉, 스택에 넣는다
⇒ $ra와 $a0에 있는 값 보존을 위해
4.
$a0값이 1보다 작으면 $t0는 1, 그렇지 않으면 0
5.
$t0가 0(zero)이면 L1으로 이동
6.
$v0를 1로 설정하ㅗ
7.
stack pointer에 다시 + 9
8.
jump return : $ra 레지스터로 이동
L1
1.
$a0에 -1연산
2.
fact로 이동
3.
load word(lw)명령어로 0($sp)의 값을 $a0로 복원
4.
load word(lw)명령어로 4($sp)의 값을 $ra로 복원
5.
stack pointer값에 다시 +8
6.
$a0 와 $v0 곱해 $v0에 복사
7.
jump return : $ra 레지스터로 이동. caller 로 돌아감
Local Data on the Stack
frame pointer(fp)와 stack pointer(sp)
•
c프로그램에서 local data(지역변수)는 stack에 할당이 된다.
•
sp는 현재 stack의 top에 있는 값을 가리킨다
•
Procedure Frame(activation record)
◦
함수 실행시 만들어지는 함수를 위한 frame
◦
fp는 frame의 시작점을 가리킨다.
◦
stack storage를 관리하기 위해 몇몇 compilers의해 이용된다.
Memory Layout
•
Text : program code (명령어)
•
Static data: global variables
◦
e.g., static variables in C, constant arrays and strings
◦
$gp(global pointer) initialized to address allowing ± offsets into this segment. 이 segment의 중간값을 가짐
•
Dynamic data: heap
◦
e.g.., malloc in C, new in Java
•
Stack: automatic storage
Communicating with People
Character Data
•
Byte-encoded character sets
◦
ASCII : 128 characters
▪
95 graphic, 33 control
◦
Latin-1 : 256 characters
▪
ASCII, +96 more graphic characters
•
unicode: 32-bit character set
◦
JAVA, C++등에서 사용
◦
대부분의 알파벳이나 symbols 다 표현 가능
◦
UTF-8, UTF-16 : variable-length encodings. 보통 UTF-16을 많이 사용
Byte/Haftword Operations
bitwise operations사용 가능
MIPS byte/halfword load/store
•
string processing is a common case
sign extend to 32 bits in rt = 읽어서 sign extend해서 32bit로 확장해 넣음
lb rt, offset(rs) : lb=load byte - offset(rs)에서 한 바이트 읽어서 rt에 넣음
lh rt, offset(rs) : lh=load halfword - offset(rs)에서 word의 절반(메모리의 절반) 읽어서 rt에 넣음
•
zero extend to 32 bits in rt = 읽어서 zero extend해서 32bit로 확장해 넣음
lbu rt, offset(rs) : lbu=load byte unsigned
lhu rt, offset(rs) : lhu=load byte unsigned
•
store just rightmost byte/halfword
sb rt, offset(rs) : 하위 1바이트 읽어서 저장
sh rt, offset(rs) : word 하위 절반 읽어서 저장
String Copy Example
•
C code:
void strcpy (char x[], char y[])
{ int i;
i = 0;
while ((x[i]=y[i])!='\0')
i +=1;
}
C
복사
•
addresses of x, y in $10, $a0
•
i in $s0
x[i]와 y[i]가 null이 아닐 때까지 x[i]에 y[i]를 복사, i는 1씩 증가
•
MIPS Code
strcpy:
1.
sp값 4만큼 빼줌 - 4바이트 할당
2.
$s0 값 sp 에 저장
3.
$s0를 0으로 초기화
L1:
1.
$s0와 $a1 더해서 $t1에 저장
2.
$t1 에서 한바이트 읽어 $t2에 저장
3.
$s0와 $a0 더해 $t3에 저장
4.
$t2에서 한 바이트 읽어 0($t3)으로 복사. 1,2로 읽은 y[i]값을 x[i]로 복사해주는 과정이다
5.
t2가 0이면 L2, 아니면 6으로
6.
$s0에 +1 (i+=1)해주고
7.
L1으로 점프!
L2:
1.
$s0값을 복원시키고
2.
sp값도 +4해서 복원시키고
3.
caller로 간다