[Mips] Mips ISA 정리
MLP, ISA
MLP
- MLP - Machine Language Program
기계가 이해하는 머신코드는 0과 1로만 이루어져있다.
MIPS 아키텍처를 위한 코드는 사람이 바로 이해할수는 없다.
그래서 어셈블리 명령어가 사람이 이해할 수 있게 머신 코드와 1:1 대응되어있고, 어셈블리로 작성한 코드는 어셈블러
를 통해 머신코드로 변환된다.
그럼에도 불구하고 개발자들은 HLL(high-level language)을 만들어서 더욱 사람이 읽기 쉬운 코드로 바꾸었다.
그렇게 나온 것이 C이다.
C이전에도 몇몇 고수준 언어들이 있었으나, 오늘날 운영체제에 직접 사용된 고수준 언어는 C이다.
결국, C로 작성된 코드도 머신이 이해할 수 있게 바뀌어야하는데, 이걸 직접 수행하는 것이 아닌, C-Compiler
가 어셈블리로 변환한다.
C컴파일러에는 GCC, clang등이 있고, 특정 아키텍처 타겟
을 지정해 원하는 아키텍처에서 코드가 돌아갈 수 있도록 할 수 있다.
- 요약:
- HLL(C언어) ->
C-Compiler
컴파일 - 어셈블리(특정 아키텍처를 위한) ->
어셈블러
- 머신코드(특정 아키텍처를 위한)
- HLL(C언어) ->
ISA
- ISA - Instruction Set Architecture
명령집합구조는 마이크로 프로세서가 인식해서 기능을 이해하고 실행할 수 있는 명령어 집합을 의미한다.
- 명령들의 형식과 내용을 정의한다.
- 하드웨어와 소프트웨어를 분리해서
이 사이에서 가교역할을 한다.
- ARM, X86, 그리고 MIPS등이 있다.
종류
- ISA에는 크게 2가지 종류가 있다.
- RISC(Reduced Instruction Set Computer) : 최소한의 명령어로 CA를 정의(ex, ARM)
- CISC(Complex Instruction Set Computer) : 복잡한 명령어로 CA를 정의하는 철학(ex, X86)
컴퓨터의 메인컨셉
컴퓨터의 메인 컨셉은 폰-노이만 아키텍처를 기반으로한다.
폰-노이만 아키텍처는 컴퓨터를 CPU
와 Memory
로 설명한다.
Memory
: 명령(프로그램)을 저장하는 곳CPU
: 명령을 순차적으로 실행하는 곳
- 명령들은 모두 데이터이기때문에 bit값으로 메모리에 저장되어있다.
- CPU는
순차적으로 명령을 실행
하기 위해서Program Counter
라는 특수한 레지스터가 있어서 다음에 처리할 명령어의 주소를 가지고있다.- 운영체제가 CPU에서 프로세스를 실행시킬때, PCB라는 구조체로 관리하고있는데, 이 구조체 안에도 PC가 존재한다.(다음에 실행할 주소)
- PC를 사용해서 명령이 수행되는 것은 아래 3개의 단계를 거친다.
- Fetch : PC가 가리키고있는 메모리 주소로부터 명령어를 Fetch한다.
- Execute : 명령을 수행한다.
- Update : PC를 Update해 다음 명령을 가리킨다.
소프트웨어, 하드웨어 관점의 컴퓨터
-
Application Software
- HLL로 작성된 코드
-
System Software
- 컴파일러: HLL을 머신 코드로 번역
- OS: 코드를 수행
- I/O 관리
- 메모리와 저장공간 관리
- 자원공유 및 task scheduling
-
Hardware
- 프로세서, 메모리, I/O 장치
MIPS
- Mips는 ISA(instruction set architecture)로써 레지스터와 메모리 주소를 처리하는 low-level 프로그래밍 언어
- Mips 파이프라인 단계가 연동되지 않은 마이크로프로세서를 나타낸다.
- MIPS R4000에는 아래와 같은 Instruction Category가 있다.
- Arithmetic
- Load/Store
- Jump/Branch
- Floating Point
- Memory Management
- Special
- 이 중, 핵심은 1,2,3이다.
Formats
- 이러한 명령은 크게 3가지 포맷으로 구현되어 있다.
- 각 명령어는 모두
32bit
로 구성된다. - 32bit 아키텍처에서 특정 주소를 가리키기 위해선 2^5 = 32이므로 5bit가 주소지정에 사용된다.
- R format
- R 형식은
레지스터를 사용
하는 명령어 형식. - 이 형식의 명령어는 대개
산술 논리 연산, 레지스터 값 로드 및 저장
등의 명령어. - R 형식 명령어는
- 6 비트의 연산 코드(OpCode),
- 5 비트의 첫 번째 소스 레지스터(RS),
- 5 비트의 두 번째 소스 레지스터(RT),
- 5 비트의 대상 레지스터(RD),
- 5 비트의 쉬프트 양(Shift Amount)
- 6 비트의 기능 코드(Funct)로 구성.
- I format
- I 형식은
즉시 값(Immediate Value)을 사용
하는 명령어 형식. - 이 형식의 명령어는 대개
상수 로드, 분기 및 메모리 연산
등의 명령어. - I 형식 명령어는
- 6 비트의 연산 코드(OpCode),
- 5 비트의 소스 레지스터(RS),
- 5 비트의 대상 레지스터 또는 기록을 위한 레지스터(RT),
- 16 비트의 즉시 값(Immediate Value)으로 구성.
- J Format
- J 형식은 점프 명령어 형식.
- 이 형식의 명령어는 대개
분기 명령어
입니다. - J 형식 명령어는
- 6 비트의 연산 코드(OpCode) 및
- 26 비트의 점프 대상 주소(Target Address)로 구성됩니다.
register convention
Register Number | Register Name | Description |
---|---|---|
0 | $zero | 0 값 |
1 | $at | 어셈블러에서 사용하는 임시레지스터이다. |
2~3 | $v0, $v1 | 표현식 평가 및 함수 결과 |
4~7 | $a0 ~ $a3 | 서브루틴을 위한 첫 4개 파라미터 |
8~15, 24~25 | $t0 ~ $t9 | 임시 변수 |
16~23 | $s0 ~ $s7 | 최종적으로 연산된 결과를 표현하는 저장된 값 |
31 | $ra | 반환 주소 |
Syntax
- Operation은 기본적으로
최대 3개의 피연산자
를 가질 수 있다.
Arithmetic
Instruction | Example | Meaning | Comments |
---|---|---|---|
add | add $1, $2, $3 | $1 = $2 + $3 | |
subtract | sub $1, $2, $3 | $1 = $2 - $3 | |
add immediate | addi $1, $2, 100 | $1 = $2 + 100 | immediate == constant number |
add unsigned | addu $1, $2, $3 | $1 = $2 + $3 | 값들은 부호없는 정수로 취급된다. |
subtract unsigned | subu $1, $2, $3 | $1 = $2 - $3 | 값들은 부호없는 정수로 취급된다. |
add immediate unsigned | addiu $1, $2, 100 | $1 = $2 + 100 | 값들은 부호없는 정수로 취급된다. |
multiply without overflow | mul $1, $2, $3 | $1 = $2 * $3 | 결과값은 반드시 32bit이다. |
multiply | mult $2, $3 | $hi, $low = $2 * $3 | 상위 32bit는 hi register에, 하위 32bit는 lo register에 저장된다. |
divide | div $2, $3 | $hi, $low = $2 / $3 | 나머지는 hi에 저장되고, 몫은 lo에 저장된다 |
Logical
Instruction | Example | Meaning | Comments |
---|---|---|---|
and | and $1, $2, $3 | $1 = $2 & $3 | bitwise AND |
or | or $1, $2 ,$3 | $1 = $2 | $3 | bitwise OR |
and immediate | andi $1, $2, 100 | $1 = $2 & 100 | bitwise AND with immediate value |
or immediate | or $1, $2, 100 | $1 = $2 | 100 | bitwise OR with immediate value |
shift left logical | sll $1, $2, 10 | $1 = $2 « 10 | shift left by constant number of bits |
shift right logical | srl $1, $2, 10 | $1 = $2 » 10 | shift right by constant number of bits |
Data Transfer
Instruction | Example | Meaning | Comments |
---|---|---|---|
load word | lw $1, 100($2) | $1= Memory[$2 + 100] | 메모리를 레지스터에 복사한다. |
store word | sw $1, 100($2) | Memory[$2 + 100] = $1 | 레지스터를 메모리에 복사한다. |
load upper immediate | lui $1, 100 | $1 = 100 x 2^16 | 상수를 32bit중 상위 16bit에 load한다. 하위 16bit는 0이된다. ex) lui $t1, 100 => 0x00640000 |
load address | la $1, label | $1 = Address of label | label의 연산된 주소를 레지스터에 불러온다. |
load immediate | li $1, 100 | $1 = 100 | 상수값을 레지스터에 불러온다 |
move from hi | mfhi $2 | $2 = hi | 특수 레지스터 hi를 일반 레지스터에 복사한다. |
move from to | mflo $2 | $2 = lo | 특수레지스터 lo를 일반 레지스터에 복사한다. |
move | move $1, $2 | $1 = $2 | 레지스터를 레지스터에 복사한다. |
Conditional Branch
Instruction | Example | Meaning | Comments |
---|---|---|---|
branch on equal | beq $1, $2, 100 | if ($1 == $2) go to PC + 4 + 100 | 레지스터 값이 같은지 테스트한다. |
branch on not equal | bne $1, $2, 100 | if ($1 != $2) go to PC + 4 + 100 | 레지스터 값이 다른지 테스트한다. |
branch on grater than | bgt $1, $2, 100 | if ($1 > $2) go to PC + 4 + 100 | |
branch on grater than or equal | bge $1, $2, 100 | if ($1 >= $2) go to PC + 4 + 100 | |
branch on less than | blt $1, $2, 100 | if ($1 < $2) go to PC + 4 + 100 | |
branch on less than or equal | ble $1, $2, 100 | if ($1 <= $2) go to PC + 4 + 100 |
Comparision
Instruction | Example | Meaning | Comments |
---|---|---|---|
set on less than | slt $1, $2 ,$3 | if ($2 < $3) $1 = 1; else $1 = 0 | 만약 $2가 $3보다 작으면 $1 을 1로 set, 아니라면 0으로 set |
set on less than immediate | slti $1, $2 ,100 | if ($2 < 100) $1 = 1; else $1 = 0 | $2가 100보다 작으면 $1을 1로 set, 아니라면 0으로 set |
Unconditioanl Jump
Instruction | Example | Meaning | Comments |
---|---|---|---|
jump | j 1000 | go to address 1000 | 타겟 주소로 Jump한다. |
jump register | jr $1 | $1안에 저장된 주소로 이동한다. | switch, procedure return에 사용된다. |
jump and link | jal 1000 | $ra = PC + 4로 set한 후 1000 주소로 이동한다. | procedure call 만들때 사용되며, return될 주소를 $ra에 저장한다. |
System calls
- 어셈블리에서 시스템콜은 $v0에 시스템콜의 종류를 명시하는 정수를, 그리고 a0, a1의 argument register에 시스템콜의 결과가 반환된다.
- 사용자에게 출력하는 시스템콜은 $a0,혹은 f12레지스터를 argument로 사용하며, 입력받는 레지스터는 $v0와 $f0로 입력값이 전달되며, 동적할당의 경우 $a0에 길이를 담고 $v0에 시작주소가 리턴된다.
Service | Operation | service number(in $v0) | Arguments | Results |
---|---|---|---|---|
print_int | 32bit 정수를 출력한다. | 1 | $a0에 출력할 정수를 담는다. | None |
print_float | 32bit 부동소수점 수를 출력한다. | 2 | $f12에 출력할 부동소수를 담는다. | None |
print_double | 64bit 부동소수점을 출력 | 3 | $f12에 출력할 double을 담는다. | None |
print_string | null로 끝나는 문자열을 출력한다. | 4 | $a0 에 출력할 문자열의 시작주소를 담는다. | None |
read_int | 사용자로부터 정수를 입력받는다. | 5 | None | $v0에 사용자가 입력한 정수가 담긴다. |
read_float | 사용자로부터 32bit 부동소수를 입력받는다. | 6 | None | $f0에 사용자가 입력한 소수가 담긴다. |
read_double | 사용자로부터 64bit 부동소수를 입력받는다. | 7 | None | Double이 $f0에 담긴다. |
read_string | 사용자로부터 문자열을 입력받는다. | 8 | $a0에 입력받은 문자열의 시작포인터를, $a1에 문자열의 길이를 담는다. | None |
sbrk | 동적할당에 사용, n길이를 가진 메모리 블록의 시작주소를 리턴. | 9 | $a0 = 길이 | address in $v0 |
exit | 프로그램을 멈춘다. | 10 | None | None |
print_char | 1개 문자 출력 | 11 | $a0 에 출력할 문자를 담는다. | None |
read_char | 사용자로부터 문자 1개 입력받는다. | 12 | None | Char는 $v0에 리턴된다. |
exit2 | 프로그램을 멈추고, 정수를 반환한다. | 17 | $a0 에 정수가 담긴다. | None |
assembler directives
Directive | Result |
---|---|
.data | 데이터 영역 시작을 알리는 지시자, 다음에 오는 코드는 변수, 상수, 배열 등 데이터를 정의한다. |
.text | 코드영역을 알리는 지시자. 다음에 오는 코드는 명령어(instruction)으로 해석된다. |
.word w1, … , wn | n개의 32bit 값을 연속적인 메모리 word에 저장한다. |
.half h1, …, hn | n개의 16bit 값을 연속적인 메모리 word에 저장한다. |
.ascii str | 아스키 문자열을 메모리에 저장한다. 문자열은 쌍따옴표로 묶여있다. |
.asciiz str | 아스키 문자열을 메모리에 저장하는데, null로 끝나게끔한다. |
.space n | 나중에 사용하기위해 n-byte의 비어있는 메모리 영역을 만든다. |
.align n | 데이터를 정렬하는 지시자. 다음 데이터 영역을 2^n byte 영역에 맞춰 정렬한다. .byte, .half등으로 메모리 영역이 4byte에 맞춰져있지 않을때 .align 2하고 밑의 변수를 선언하면 이전 변수메모리와는 상관없이 새로운 4byte영역부터 생성된다. |
.globl | 전역(global) 심볼을 선언하는 지시자입니다. 다른 파일에서 참조할 수 있는 전역 변수나 함수 등을 정의할 때 사용됩니다. |
- half와 byte가 동시에 선언될때
- 최상위 byte가 패딩이되며
|padding(1byte) | half(2byte) | byte(1byte)|
이렇게 메모리 상에 위치한다.
- 최상위 byte가 패딩이되며
댓글남기기