1. MIPS 레지스터
Name | Register Number | Usage | Calling Convention |
$zero | 0 | zero 레지스터에는 상수 0이 들어감. | |
&at | 1 | at 레지스터는 어셈블러가 사용하는 임시공간이다. | |
$v0 - $v1 | 2 - 3 | 함수의 리턴 값으로 사용된다. | Caller Svae |
$a0 - $a3 | 4 - 7 | 매개변수를 저장하는 레지스터이다 | |
$t0 - $t7 | 8 - 15 | 임시변수로 사용되는 레지스터로 값이 변할 수 있다. | |
$s0 - $s7 | 16 - 23 | 상수 값을 저장하는 레지스터로 불변상태이다. | Callee Save |
$t8 - $t9 | 24 - 25 | 임시변수로 사용되는 레지스터로 값이 변할 수 있다. | Caller Save |
$k0 | 26 | OS Kernel | reserved |
$k1 | 27 | OS Kernel | |
$gp | 28 | 전역 포인터 레지스터 | Caller Svae |
$sp | 29 | 스택 포인터 레지스터 | Preserved |
$fp | 30 | 프레임 포인터 레지스터 | |
$ra | 31 | returen address | Caller Save : jar |
위 레지스터들을 정리하면, 우선 $fp와 $sp에 대해 정리하자. 아래 그림을 보면 메모리 구조에 push가 되기전의 두 레지스터의 위치와 push가 되었을때 레지스터가 가리키는 주소의 위치를 그림으로 그려보았다.
- $sp (29번) 레지스터는 스택 포인터 레지스터로 현재 CPU가 실행하려는 명령어가 있는데 그 명령어의 함수 스택 프레임의 끝나는 주소를 가리키고 있다.
- $fp (30번) 레지스터는 스택 포인터 레지스터로 현재 CPU가 실행하려는 명령어의 함수 스택 프레임의 첫 주소를 가리킨다.
- $ra(31번) 레지스터는 Caller Save 방식을 하는데 Caller에서 Callee로 실행이 넘어가고 Callee의 실행이 끝났다면 다시 원래 Caller인 스택 프레임으로 복귀 해야한다. 그 복귀 주소인 return addree를 가지고 있는 변수로 Caller Save방식으로 Caller의 스택 프레임에 저장해야한다. (Calling Convention에 관한 내용은 "컴퓨터 구조 4번 포스팅"을 참조 하자.)
- $v0 - $v1 (2 -3번) 레지스터는 현재의 Caller가 이전의 Caller에게로부터 받은 함수의 리턴 값이 있었을것이다. 그 값을 저장한 레지스터 변수로 Callee로 실행이 넘어갈때 이 값을 store 해줘야한다. 따라서 Caller Save 방식으로 스택 프레임에 저장한다.
- $a0 - $a3 (4-7번) 레지스터 역시 Caller-save인데 이 값은 현재 CPU에서 실행되고 있는 함수의 매개변수 값들이 저장되어 있는 레지스터 (4개가 넘었다면 초과된 매개변수는 Caller Stack frame에 저장되어있다.) 이다.
- $t0 - $t9 레지스터는 함수 실행과정 값이 변해도 되는 tempoary 변수를 저장하는 레지스터이다.
- $s0 - $s7 레지스터는 함수 실행과정 상수 값이 저장되어 있는 레지스터이다.
이러한 레지스터들은 아래 MIPS 문법 정리서 어떤 상황에서 사용되는지 확인하며 개념을 익힐 수 있다.
3. MIPS의 3가지 형태
Type | format | |||||
R-format | opcode (6) | rs (5) | rt (5) | rd (5) | shamt (5) | funct (6) |
I-format | opcode (6) | rs (5) | rt (5) | immediate (16) | ||
J-format | opcode (6) | address (26) |
- R-format은 두 개의 피연산자를 차례로 rs와 rt에 저장하고 연산 결과를 rd에 저장하는 구조이며 op코드와 funct 코드로 어떤 명령어인지를 나타냅니다. shamt는 shift 연산을 사용할 때 사용하는 레지스터이며 shift 연산이 아니면 0입니다. 대표적으로 add, sub, mul, div, and, or 등 2개의 피연산자의 연산과 그 결과가 필요하는 형식인 경우 사용한다.
- I-format은 레지스터가 아닌 메모리에 접근하거나, 상수를 반드시 사용해야하는 경우 사용한다. 배열에 접근하는 경우 배열의 base를 레지스터에 저장하고 offset(몇 번째 인덱스냐?)를 immediate로 나타내어 메모리에 저장된 배열 요소를 가져오는 예시가 있습니다. 주로 lw, sw, branch, addi, lb, sb, lh, sh 등의 명령을 사용할때 I-format을 사용한다. op는 opcode이며 rs는 base로 소스 레지스터를 나타내고 rt는 타겟 레지스터를 나타낸다. immediate는 offet또는 상수를 나타낸다.
- J-format은 Jump로 Jump할 opcode 명령어가 있고 이동할 주소를 26비트의 주소필드로 나타낸다. 예를 들어 j A1이러면 A1 레이블로 바로 점프를 하게 된다.
간단하게 3가지 MIPS 형태에 대해 정리해보았다. 아래 MIPS 문법에서 3가지 형태가 어떻게 사용되는지 확인하며 개념을 익힐 수 있다.
4. MIPS문법: Arithmetic
명령어 종류 | 예시 | 내용 | |
add | add $s1, $s2, $s3 | $s1 = $s2 + $s3 | 두 레지스터의 값을 더한다. |
subtract | sub $s1, $s2, $s3 | $s1 = $s2 - $s3 | 두 레지스터의 값을 뺀다. |
add immediate | addi $s1, $s2, 20 | $s1 = $s2 +20 | I-format 형태로 작성되며 |
add $s1, $s2, $s3의 명령어는 R-format으로 작성되며 아래와 같다.
opcode | rs | rt | rd | shift | funct |
6bit opcode | s2 (19) | s3 (18) | s1 (17) | 0 | 6bit funct |
addi $s1, $s2, 20 명령어는 I-format으로 작성되며 immediate의 상수 값을 더하는데 사용된다.
opcode | rs | rt | immediate | ||
6bit opcode | s2 (19) | s1(17) | 20 |
5. MIPS문법: Data transfer
명령어 종류 | 예시 | 내용 | |
load | lw $s1, 20($s2) | $s1 = address[$s2+20] | $s1에 메모리 값의 load한다. |
store | sw $s1, $s2, $s3 | address[$s2+20] = $s1 | $s1에 값을 메모리로 store한다. |
lw $s1 20($s2) 명령, lw $s1 20($s2)명령 모두 I-format으로 서로 반대 수행을 한다.
opcode | rs | rt | immediate | ||
6bit opcode | s2 (19) | s1(17) | 20 |
6. MIPS문법: Logical
명령어 종류 | 예시 | 내용 | |
and | and $s1, $s2, $s3 | $s1 = $s2 & $s3 | $s1에 $s2와 $s3를 and연산 결과를 저장 |
or | or $s1, $s2, $s3 | $s1 = $s2 | $s3 | $s1에 $s2와 $s3를 or연산 결과를 저장 |
nor | nor $s1, $s2, $s3 | $s1 = ~($s2 | $s3) | $s1에 $s2와 $s3를 nor연산 결과를 저장 |
shift left | sll $s1, $s2, 10 | $s1 = $s2 << 10 | $s1에 $s2에서 10비트를 왼쪽으로 옮겨 저장 |
shift right | srl $s1, $s2, 10 | $s1 = $s2 >> 10 | $s1에 $s2에서 10비트를 오른으로 옮겨 저장 |
위 명령어들은 모두 R-format으로 구성된다.
sll $s1, $s2, 10 명령어는 아래와 같은 R-format의 MIPS 어셈블리언어로 번역된다.
opcode | rs | rt | rd | shift | funct |
6bit opcode | s2 (19) | s3 (18) | s1 (17) | 10 | 6bit funct |
7. MIPS문법: branch
명령어 종류 | 예시 | 내용 | |
branch on equal | beq $s1, $s2, 25 | if($s1==$s2) go to PC +4+100 | $s1과 $s2가 같다면 PC+4+100한다. |
not equal | ben $s1, $s2, 25 | if($s1!=$s2) go to PC +4+100 | $s1과 $s2가 다르다면 PC+4+100한다. |
less then | slt $s1, $s2, $s3 | if($s2<$s3) $s1=1 else $s1=0 | $s2<$s3이면 $s1 = 1한다. |
less then immediate | slti $s1, $s2, 20 | if($s2<$20) $s1=1 else $s1=0 | $s2<20이면 $s1 = 1한다. |
beq, ben, slt는 R-fotmat을 사용한다. slti는 I-format을 사용한다.
beq $s1, $s2, 25 명령에서 먄약 $s1==$s2 라면 다음 명령어의 주소를 가리키는 PC를 PC+4+100하는데 이 4+100을 하는 이유는 우선 PC는 현재 명령어를 가리키고 있기 때문에 다음 명령어를 가리키기 위해 다음 명령의 메모리 주소를 가리켜 +4(word)를 한다. 그리고 같다면 PC를 25만큼 메모리 주소를 이동하는데 한 명령에서 다음 명령까지 4byte 차이가 나므로 25x4=100byte만큼 이동을 해야한다. 따라서 PC+4+100인 것이다.
8. MIPS문법: jump
명령어 종류 | 예시 | 내용 | |
jump | j 100 | go to 400 | 100x4만큼 메모리 주소를 jump한다 |
jump register | jr $ra | go to $ra | $ra에 저장된 return address로 돌아온다. |
jump and link | jal 25 | $ra=PC+4; go to 100 | $ra에는 PC+4를 하고, 100만큼 주소 이동 |
j 명령은 단순히 jump하는 것이다. 현재 명령어에서 100번째 명령으로 이동하란 뜻이 되기 때문에 메모리 주소를 100x4인 400만큼 jump 하게 된다. (한 명령어당 4byte가 MIPS 체계이기 때문이다.)
jal 명령언 $ra 레지스터에 다음 명령어를 가리킬 수 있도록 PC+4를 하고 25번째 명령어로 jump 하란 뜻이다. 따라서 현
재 메모리 주소에서 100byte만큼 메모리 주소를 jump 하게 된다.
jr 명령어는 $ra에 저장된 return address로 되돌아오라는 명령어이다.
'전공 > 컴퓨터 구조' 카테고리의 다른 글
5. CPI 계산과 CPU time 구하기 (0) | 2021.12.27 |
---|---|
6. Processor Design (0) | 2021.10.29 |
4. Calling Convention(Caller-save, Callee-save, Hybrid) (0) | 2021.10.07 |
2. ISA란? (0) | 2021.10.07 |
1. 프로그램의 번역과 실행 과정 (0) | 2021.10.07 |