MIPS 시스템
1980년대 스탠포드 대학에서 John Hennessy와 그의 동료들에 의해 개발
디자인 원리
- 규칙적인 것이 간단성을 위해 좋음
- 많이 발생되는 사항을 빨리 처리함
- 적을수록 빠름
- 좋은 설계는 좋은 절충안을 요구함
설계 원칙 1
규칙적인 것이 간단성을 위해 좋음
- 일관성 있는 명령어 형태
- 같은 수의 피연산자 => 2개의 source와 1개의 destination
ex 1) 덧셈 Addition
High-level code MIPS assembly code
a=b+c; add a, b, c
=> b와 c를 더한 뒤 a에 저장
ex 2) 뺄셈 Subtraction
High-level code MIPS assembly code
a=b-c; sub a, b, c
=> b에서 c를 뺀 뒤 a에 저장
설계 원칙 2
많이 발생되는 사항을 빨리 처리함 (복잡한 명령어를 여러 개의 단순한 명령어로 쪼개는 것)
- MIPS: 단순하고, 많이 사용되는 명령어를 포함
- 명령어를 해석하고 실행하는 하드웨어: 단순하고 빠름
- 복잡한 명령어는 여러개의 단순한 명령어로 수행
High-level code MIPS assembly code
a = b + c – d; add t, b, c # t = b + c
sub a, t, d # a = t - d
설계 원칙 3
적을수록 빠름
MIPS: 적은수의 레지스터를 포함
32개의 레지스터 (323 비트 또는 64 비트)
32개의 레지스터로 부터 데이터를 획득하는 것이 1000개의 레지스터 또는 메모리로 부터 데이터를 획득하는 것 보다 빠름
MIPS 레지스터 세트
이렇게 32개의 레지스터에 각자 역할을 정해 두고 어셈블리의 형태를 짠 것이 MIPS 구조
ex) 레지스터를 사용한 명령어
High-level code MIPS assembly code
a = b + c; # $s0 = a, $s1 = b, $s2 = c
add $s0, $s1, $s2
High-level code MIPS assembly code
a = b + c - d; # $s0 = a, $s1 = b, $s2 = c, $s3=d
sub $t0, $s2, $s3
add $s0, $s1, $t0
워드 주소 메모리
1Word=4Byte
워드 주소 메모리 읽기
(1) load 명령어 (lw)
Assembly code
lw $s3, 1($0) # read memory word 1 into $s3
->워드 1번지에서 데이터를 가져와서 $s3 레지스터 넣어라
(2) store 명령어 (sw)
Assembly code
sw $t4, 0x3($0) # # write the value in $t4
# to memory word 3
->t4 레지스터에 있던 값을 워드 3번지에 데이터 저장
즉 임시 레지스터에 저장되어 있던 값이 40F30788이었던 것!
바이트(byte) 주소 메모리
주소 체계가 달라짐
바이트 주소 메모리 읽기
(1) load 명령어 (lw)
MIPS Assembly code
lw $s3, 4($0) # read word at address 4 into $s3
->4번지에 있는 데이터를 가지고 와서 s3레지스터에 넣겠다 (가지고 오는 양은 1word, 바이트 단위로 다루는 것 X)
레지스터에 들어가는 값은 F2F1AC07
(2) store 명령어 (sw)
MIPS Assembly code
sw $t7, 12($0) # write $t7 into address 12
->t 레지스터의 데이터를 12번지에 넣어라
임시레지스터에 들어가 있던 값은 40F30788이었음
Big-Endian vs. Little-Endian
데이터를 읽어오는 방식에 대한 이야기
MSB: 제일 높은 비트
LSB: 제일 낮은 비트
주로 리틀 엔디안 방식으로 데이터를 읽어 옴
예제
$t0의 값이 0x23456789라고 가정. 아래의 프로그램이 Big-Endian 시스템과 Little-Endian 시스템에서 수행한 후에 $s0의 값은?
sw $t0, 0($0) Big-Endian: $s0 = 0x00000045
→
lb $s0, 1($0) Little-Endian: $s0 = 0x00000067
(**한 바이트만 읽겠다)
Big-Endian의 저장방향: → Little-Endian의 저장방향: ←
Big-Endian 방식으로 읽게 되면 MSB부터 읽게 되므로 45, Little-Endian으로 읽어 오게 되면 주소 체계가 바뀌어 LSB부터 읽게 되므로 67이 저장
(데이터를 읽어오는 방식이 다르기 때문에 각 방식으로 읽어왔을 때 $s0에 저장되는 값이 다름)
설계 원칙 4
좋은 설계는 좋은 절충안을 요구함
- 다중 명령어 형태는 융통성 제공
(1) add, sub: 3개의 레지스터 피연산자 사용
(2) lw, sw: 2개의 레지스터 피연산자와 상수 사용
-> 적은 수의 명령어 형태를 유지
기계어
- 명령어들의 이진 표현 (0 또는 1)
- 32비트 명령어
명령어 형태
(1)R-Type
(2)I-Type
(3)J-Type
(1)R-Type
레지스터 타입
3개의 레지스터 피연산자(오퍼랜드) 사용
- rs,rt: source 레지스터
- rd: destination 레지스터
다른 필드
- op: operation 코드 (op 코드)
모든 R-Type 명령어의 op 코드값: 0
- funct: function
- shamt: shift 명령어에서 사용되는 shift 양
17번 레지스터와 18번 레지스터를 더해서 16번 레지스터에 넣어 주고 op 코드는 항상 0, 곱하기 나누기 계산이 없으므로 shamt도 0 더하는 명령어라 funct값은 32
11번 레지스터에서 13번 레지스터를 뺀 뒤 8번 레지스터에 넣어 준다 op 코드는 항상 0, 곱하기 나누기 계산이 없으므로 shamt도 0 빼는 명령어라 funct 값은 34
이것을 기계어 코드로 바꾸면,
(2)I-Type
- 즉시값(Immediate) 타입
- 3개의 피연산자(오퍼랜드)
rs,rt: 레지스터 피연산자
imm: 16비트 즉시값(immediate)
다른 필드
op: operation 코드 (op 코드)
각각의 I-type 명령어는 개별적인 op 코드값을 갖음
17번 레지스터와 5를 더해서 16번 레지스터에 넣는다 더하는 명령어라 op 코드는 8
19번 레지스터에서 12라는 함수값을 빼서 8번 레지스터에 넣는다
32를 10번 레지스터에 넣어라
4를 17번 레지스터에 저장해라
이를 기계어로 바꾸면
(3)J-Type
- Jump 타입
- 1개의 피연산자(오퍼랜드)
addr: 주소 피연산자
- 다른 필드
op: operation 코드 (op 코드)
저장된 프로그램
- 32비트 명령어와 데이터는 메모리에 저장됨
- 프로그램 실행
프로그램을 메모리에 저장
메모리에 있는 명령어들을 순차적으로 읽어서 실행
프로그램 카운터 (PC)를 이용해서 다음에 수행할 명령어 파악
기계어 코드 해석
(1) opcode 분석
(2) opcode가 0이면,
R-type 명령어
func 비트를 통해서 명령어 기능 분석
(3) opcode가 0이 아니면,
I-type 또는 J-type 명령어
어셈블리 코드를 Field Values로 바꾸고 Field Vlaues를 Machine Code로 바꾸고 그것을 16진수로 바꾸는 과정
논리 명령어
- and, or, xor, nor
and: 원치 않는 비트를 0으로 만드는 비트 마스킹에 유용
or: 두 레지스터의 비트를 결합시키는데 유용
nor: 비트들을 역전시키는데 유용
- andi, ori, xori
16비트 즉시값(immediate)이 and, or, xor의 피연산자로 포함
16비트 즉시값은 32비트로 변환될때, 제로 확장(패딩)
조건부 분기(beq)
beq: 두 레지스터의 값이 동일할 경우 분기
addi $s0, $0, 4 # $s0 = 0 + 4 = 4
addi $s1, $0, 1 # $s1 = 0 + 1 = 1
sll $s1, $s1, 2 # $s1 = 1 << 2 = 4
(sll은 비트연산임. 첫 번째 비트 연산을 했을 떄는 0010, 2가 됨 두 번째 비트연산을 하면 0100, 4가 됨.)
beq $s0, $s1, target # branch is taken
($s0, $s1이 같으면 target으로 분기해라. 이때 두 레지스터의 값이 같기 때문에 target으로 이동)
addi $s1, $s1, 1 # not executed
(분기했으므로 실행하지 않음)
sub $s1, $s1, $s0 # not executed
(분기했으므로 실행하지 않음)
target:
add $s1, $s1, $s0
조건부 분기(bne)
bne: 두 레지스터의 값이 동일하지 않을 경우 분기
addi $s0, $0, 4 # $s0 = 0 + 4 = 4
addi $s1, $0, 1 # $s1 = 0 + 1 = 1
sll $s1, $s1, 2 # $s1 = 1 << 2 = 4
bne $s0, $s1, target # branch not taken
($s0, $s1이 다르면 target으로 분기해라. 두 레지스터의 값이 같기 때문에 분기 X)
addi $s1, $s1, 1 # $s1 = 4 + 1 = 5
(실행됨)
sub $s1, $s1, $s0 # $s1 = 5 – 4 = 1
(실행됨)
target:
add $s1, $s1, $s0 # $s1 = 1 + 4 = 5
무조건 분기 (j)
j: 무조건 분기
addi $s0, $0, 4 # $s0 = 4
addi $s1, $0, 1 # $s1 = 1
j target # jump to target
(무조건 target으로 분기)
sra $s1, $s1, 2 # not executed
(실행 X)
addi $s1, $s1, 1 # not executed
(실행 X)
sub $s1, $s1, $s0 # not executed
(실행 X)
target:
add $s1, $s1, $s0 # $s1 = 1 + 4 = 5
무조건 분기(jr)
jr: 주소로 무조건 분기 레지스터가 가진 값을 주소로 판단하고 그 주소로 이동
0x00002000 addi $s0, $0, 0x2010
0x00002004 jr $s0
0x00002008 addi $s1, $0, 1
0x0000200C sra $s1, $s1, 2
0x00002010 lw $s3, 44($s1)
if 문
어셈블리어에선 같지 않으면 분기하고 같으면 분기하지 않는다. 바로 다음 명령어 수행
if/else 문
s3과 s4 레지스터가 같지 않으면 L1 분기 / 같으면 분기하지 않고 그 다음 명령어
j done 무조건 분기를 써서 if와 else식 구분
while문
pow가 128이 되면 while문을 빠져나오는 코드
=> $s0와 $t0가 같으면 done으로 분기. 이때 $s0는 pow고 $t0는 128이라고 선언된 상태. 즉, $s0가 128일 때 분기.
for 루프
j for 무조건 분기를 사용하여 for문 반복
Less Than 비교
뒤에 있는 두 레지스터의 값을 비교하여 만약 앞에 있는 레지스터가 더 작다면 맨 첫 번째 오퍼랜드에 있는 레지스터의 값을 1로 세팅
참고 2019 컴퓨터 구조 호준원교수님 강의노트 9
디지털 논리와 컴퓨터 설계, Harris et al.(조영완 외 번역), 사이텍미디어, 2007,
컴퓨터 구조와 원리(비주얼 컴퓨터 아키텍처), 신종홍 저, 한빛미디어, 2011
문제
Q1. MIPS 시스템 디자인 원리로 틀린 것은? ( )
ㄱ. 규칙적인 것이 간단성을 위해 좋다
ㄴ. 많이 발생되는 사항을 빨리 처리한다
ㄷ. 적을수록 느리다
ㄹ. 좋은 설계는 좋은 절충안을 요구한다
Q2~Q3. 다음은 워드 주소 메모리를 읽는 것에 관한 설명이다 맞으면 O, 틀리면 X를 선택하시오

Q2) lw $s3, 1($0)라는 어셈블리 코드는 워드 1번지에서 데이터를 가지고 와서 $s3 레지스터에 값을 넣으라는 뜻이다 ( )
Q3) sw $t4, 0x2($0)라는 어셈블리 코드는 t4 레지스터에 있던 값을 워드 2번지에 저장하란 뜻이다. 그림을 통해 t4레지스터에 저장되어 있던 값이 40F30788이었던 것을 알 수 있다. ( )
Q4) 다음은 Big-Endian과 Littl-Endian에 관한 설명이다 다음 중 틀린 것은?
1. 데이터를 읽어 오는 방식의 차이다
2. MSB는 제일 높은 비트를 말한다
3. LSB는 제일 낮은 비트다
4. 빅 엔디안의 저장 방향은 MSB->LSB, 리틀 엔디안의 저장 방향은 LSB->MSB다
5. 주로 빅 엔디안 방식으로 데이터를 읽어온다
Q5) 다음 그림은 기계어의 명령어 타입 중 하나이다. 어떠한 타입의 명령어일까? ( )

Q6) ㄱ~ㅂ까지의 어셈블리 코드 중에서 실행되지 않는 줄을 모두 고르시오 ( )

Q7) 다음은 if/else 문을 MIPS assembly code로 변형한 것이다 밑줄 친 부분에 들어갈 코드는? ( )

정답
A1. MIPS 시스템 디자인 원리로 틀린 것은? ( )
ㄱ. 규칙적인 것이 간단성을 위해 좋다
ㄴ. 많이 발생되는 사항을 빨리 처리한다
ㄷ. 적을수록 느리다
적을수록 느린 것이 아니라 빠르다
ㄹ. 좋은 설계는 좋은 절충안을 요구한다
Q2~Q3. 다음은 워드 주소 메모리를 읽는 것에 관한 설명이다 맞으면 O, 틀리면 X를 선택하시오

Q2) lw $s3, 1($0)라는 어셈블리 코드는 워드 1번지에서 데이터를 가지고 와서 $s3 레지스터에 값을 넣으라는 뜻이다 ( O )
Q3) sw $t4, 0x2($0)라는 어셈블리 코드는 t4 레지스터에 있던 값을 워드 2번지에 저장하란 뜻이다. 그림을 통해 t4레지스터에 저장되어 있던 값이 40F30788이었던 것을 알 수 있다. ( X )
sw $t4, 0x2($0)라는 어셈블리 코드는 t4 레지스터에 있던 값을 워드 2번지에 저장하란 뜻이다. 그림을 통해 t4 레지스터에 저장되어 있던 값이 01EE2842였던 것을 알 수 있다
Q4) 다음은 Big-Endian과 Littl-Endian에 관한 설명이다 다음 중 틀린 것은?
1. 데이터를 읽어 오는 방식의 차이다 (o)
2. MSB는 제일 높은 비트를 말한다 (o)
3. LSB는 제일 낮은 비트를 말한다 (o)
4. 빅 엔디안의 저장 방향은 MSB->LSB, 리틀 엔디안의 저장 방향은 LSB->MSB다 (o)
5. 주로 빅 엔디안 방식으로 데이터를 읽어온다 (x)
->주로 리틀 엔디안 방식으로 데이터를 읽어온다
Q5) 다음 그림은 기계어의 명령어 타입 중 하나이다. 어떠한 타입의 명령어일까? ( I-Type )

3개의 피연산자(오퍼랜드)를 가지는 즉시값(Immediate)타입이다
Q6) ㄱ~ㅂ까지의 어셈블리 코드 중에서 실행되지 않는 줄을 모두 고르시오 ( ㅁ, ㅂ )

ㄹ의 코드를 해석해 보면 $s0, $s1이 같으면 target으로 분기하라는 뜻이다. 이때 두 레지스터의 값이 같이 때문에 target으로 이동하게 된다 따라서 ㅁ, ㅂ는 실행되지 않는다
Q7) 다음은 if/else 문을 MIPS assembly code로 변형한 것이다 밑줄 친 부분에 들어갈 코드는? ( j done )

if/else문을 어셈블리 코드로 표현하면 j done 무조건 분기식을 써서 if식과 else식을 구분해야 한다.
'컴퓨터 구조' 카테고리의 다른 글
컴퓨터 구조 5주차 (0) | 2020.06.05 |
---|---|
컴퓨터 구조 4주차 (0) | 2020.05.28 |
컴퓨터 구조 3주차(2) (0) | 2020.05.23 |
컴퓨터 구조 3주차(1) (0) | 2020.05.23 |
컴퓨터 구조 2주차(2) (0) | 2020.04.16 |