[Chapter 04] 컴퓨터 구조에 대한 두 번째 이야기

·2022년 10월 20일

※ 아래는 윤성우 뇌를 자극하는 윈도우즈 프로그래밍 한빛미디어(주) 2022년
Chapter04(p.107 ~ 125)를 읽고 정리한 내용입니다.

01 레지스터를 디자인하자


  1. 레지스터를 몇 비트로 구성할 것인가? -> 16비트

  2. 몇 개 정도로 레지스터를 구성할 것인가? -> 8개

  3. 레지스터 각각을 무슨 용도로 사용할 것인가? -> 아래와 같이 사용

    r0r1r2r3r4r5r6r7
    irsplrpc

ir : instruction register
sp : stack pointr
lr : link register
pc : program counter

02 명령어 구조 및 명령어를 디자인하자


  1. 명령어의 길이를 몇 비트로 구성할 것인가? -> 16비트

(1) 명령어 구조

예약 연산자 저장소 피연산자1 피연산자2
#0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14 #15
#8과 #12가 0이면 숫자를 의미, 1이면 레지스터를 의미

(2) 연산
연산의 의미심볼2진 코드연산의 의미심볼2진 코드
덧셈ADD001뺄셈SUB010
곱셈MUL011나눗셈DIV100

(3) 레지스터 심볼
레지스터 심볼2진 코드레지스터 심볼2진 코드
r0000r4, ir100
r1001r5, sp101
r2010r6, lr110
r3011r7, pc111

  1. 어떤 명령어를 보낼 것인가?
    -> "레지스터 r1에 있는 값과 숫자 7을 더해서 레지스터 r2에 저장하라"
    '덧셈', '레지스터 r1', '레지스터 r2', '숫자 7'

    예약 연산자 저장소 피연산자1 피연산자2
    0 0 1 0 1 0 1 0 0 1 0 1 1 1

<결과>
구성하는 명령어의 형태에 따라서 컨트롤 유닛의 구조가 결정된다.

03 RISC vs CISC


CISC (Complex Instruction Set Computer)
: 복잡한 명령어 체계를 가지는 컴퓨터
, 명령어 수가 많고 복잡하기 때문에 성능 향상에 제한이 따름

RISC (Reduced Instruction Set Computer)
: 명령어 수를 줄이고, 명령어 길이를 일정하게 디자인한 구조
, 높은 성능을 낼 수 있음 (클럭당 처리할 수 있는 명령어의 개수가 늘어남)

04 LOAD & STORE 명령어 디자인


'02 명령어 구조 및 명령어를 디자인하자'에서 두 가지 제약사항을 걸었다.
(1) 연산결과를 레지스터에만 저장할 수 있다.
(2) 모든 피연산자에는 메인 메모리 주소값이 올 수 없다.
때문에 아래와 같은 연산을 할 수 없다.

int a = 10; // 0x10번지 할당
int b = 20; // 0x20번지 할당
int c = 0;  // 0x30번지 할당
c = a + b;

마지막 줄을 실행하기 위해서는 다음과 같은 문장을 명령어로 구성할 수 있어야 한다.
"0x10번지(a)에 저장된 값과, 0x20번지(b)에 저장된 값을 더해서 0x30번지(c)에 저장해라"

위 사항은 제약사항에 의해 처리가 불가하므로
"레지스터와 메인 메모리 사이에서 데이터를 전송할 수 있는 명령어가 필요하다."

메인 메모리에 저장된 데이터를 레지스터로 이동시키기 위한 LOAD는 110,
레지스터에 저장된 데이터를 메인 메모리로 이동시키기 위한 STORE는 111로 정의한다.

"0x10번지에 저장된 데이터를 r1로 이동한다"

연산자 목적지 소스
1 1 0 0 0 1 0 0 0 0 1 0 1 0

"0x20번지에 저장된 데이터를 r2로 이동한다"
연산자 목적지 소스
1 1 0 0 1 0 0 0 0 1 0 1 0 0

"r1, r2에 저장된 값을 더해서 r3에 결과 저장"
연산자 저장소 피연산자1 피연산자2
0 0 1 0 1 1 1 0 0 1 1 0 1 0

"r3에 저장된 값을 0x30번지에 저장"
연산자 소스 목적지
1 1 1 0 1 1 0 0 0 1 1 1 1 0

05 Direct 모드와 Indirect 모드


'04 LOAD & STORE 명령어 디자인'에서 LOAD 연산자를 구현한 부분을 보면
소스에 올 수 있는 값이 0x0000 ~ 0x00ff까지가 전부다.
만약 0x0100번지에 저장된 데이터를 참조하는 경우가 생기면 문제가 된다.
-> 즉, 메모리의 모든 영역에 대한 접근이 불가능하다 (Direct 모드의 문제점)

Indirect 모드는 명령어에서 지정하는 번지에 저장된 값을 주소값으로 참조한다.

Direct 모드는 10으로, Indirect 모드는 11로 정의한다.

int a = 10; // 0x0010번지 할당
int b = 20; // 0x0100번지 할당
int c = 0;  // 0x0020번지 할당
c = a + b;

두번째줄을 직접적으로 구현할 수 없으므로 Indirect 모드로 접근해보자

"0x0010번지에 저장된 데이터를 r1로 이동"

예약 연산자 목적지 소스
1 1 0 0 0 1 0 0 0 0 1 0 1 0

"0x0100번지에 저장된 데이터를 r2로 이동"
-> (1) r0에 4*4 저장
예약 연산자 저장소 피연산자1 피연산자2
0 1 1 0 0 0 0 1 0 0 0 1 0 0

-> (2) r2에 4*4 저장
예약 연산자 저장소 피연산자1 피연산자2
0 1 1 0 1 1 0 1 0 0 0 1 0 0

-> (3) r3에 r0의 값 * r2의 값인 256 저장 (0x0100은 십진수로 256)
예약 연산자 저장소 피연산자1 피연산자2
0 1 1 0 1 1 1 0 0 0 1 0 1 0

-> (4) r3에 저장된 주소 데이터를 메인 메모리로 이동
예약 연산자 소스 목적지
1 1 1 0 1 1 0 0 0 1 1 1 1 0

-> (5) indirect 모드로 [0x0030]의 메모리 값 읽기
예약 연산자 목적지 소스
1 1 1 1 0 0 1 0 0 0 0 1 1 1 1 0

"r1 + r2 값을 r3에 저장"
예약 연산자 저장소 피연산자1 피연산자2
0 0 1 0 1 1 1 0 0 1 1 0 1 0

0개의 댓글