명령어 구조 컴퓨터 하드웨어의 구성 프로그램 명령어 프로그램 실행 동작
컴퓨터 하드웨어의 전반적인 구성을 살펴본다. 중앙처리장치의 구성과 명령어 처리 단계를 살펴본다. 주기억장치의 역할과 동작 원리를 살펴본다. 컴퓨터 시스템에서 실행하는 프로그램 명령어의 형식과 동작 원리를 살펴본다. 프로그램이 어떻게 실행되는지를 예를 통해 살펴본다.
컴퓨터 하드웨어의 구성 중앙처리장치 주기억장치 입출력장치 프로그램 명령어를 실행하는 기능을 수행 실행 중인 프로그램과 프로그램 실행에 필요한 데이터를 일시적으로 저장 입출력장치 키보드, 모니터, 하드디스크 등으로 중앙처리장치나 주기억장치에 데이터를 입력하거나 출력하는 기능을 수행 [그림 4-1] 컴퓨터 하드웨어의 구성
시스템 버스의 종류 프로그램의 실행 과정 [표 4-1] 시스템 버스의 종류 [그림 4-2] 프로그램의 실행 과정
중앙처리장치 중앙처리장치의 구성 [그림 4-3] 중앙처리장치의 구성 [표 4-2] 중앙처리장치의 구성
레지스터의 종류 중앙처리장치의 명령어 처리 단계 인출 단계는 주기억장치에 저장된 명령어 하나를 읽어 오는 단계 해독 단계는 읽어 온 명령어를 제어 정보로 해독하는 단계 실행 단계는 해독된 명령을 실행하는 단계 [표 4-3] 레지스터 종류 [그림 4-4] 중앙처리장치의 명령어 처리 단계
주기억장치 현재 실행 중에 있는 프로그램과 이 프로그램이 필요로 하는 데이터를 일시적으로 저장하는 장치 주소 할당 : 저장된 정보를 관리하기 편하고 각 위치를 구분하기 위해 바이트 또는 워드 단위로 분할해 주소를 할당 주기억장치가 제공하는 동작 중앙처리장치가 주기억장치에 데이터를 저장하는 ‘쓰기’ 주기억장치에 저장된 데이터를 중앙처리장치로 읽는 ‘읽기’ [그림 4-5] 바이트 단위로 분할한 256바이트 크기의 주기억장치
주기억장치와 연결된 버스 [그림 4-6] 주기억장치와 연결된 버스
제어 버스 장치들을 연결하는 일을 하는데, 주소, 데이터, 제어 버스로 구분 주기억장치 주소 60의 데이터 읽기 주소 버스에 50을, 데이터 버스에 20을 전송한다. 그리고 제어 버스에 쓰기 제어 신호를 보내면 주기억장치 주소 50에 20이 저장된다. 주기억장치 주소 60의 데이터 읽기 주소 버스에 60을 전송하고, 제어 버스에 읽기 제어 신호를 보낸다. 그러면 주기억장치 주소 60에 저장된 30이 데이터 버스를 통해 중앙처리장치로 전송된다. [그림 4-7] 주기억장치 주소 50에 데이터 20 쓰기 [그림 4-8] 주기억장치 주소 60의 데이터 읽기
명령어 기본 형식 연산 코드 피연산자 명령어의 분류 중앙처리장치가 실행해야 할 동작을 나타내는 부분으로, 더하기, 곱하기, AND, OR 등을 의미하는 내용이 위치한다. 피연산자 동작에 필요한 값 또는 저장 공간(레지스터 또는 주기억장치의 주소)을 나타내는데, 피연산자 개수는 중앙처리장치에 따라 차이가 있다. 명령어의 분류 [그림 4-9] 명령어 기본 형식 [표 4-4] 명령어의 분류
주소지정 방식 0-주소 형식(zero-address instruction) 1-주소 형식(one-address instruction) 2-주소 형식(two-address instruction) 3-주소 형식(three-address instruction)
1) 0-주소 형식(zero-address instruction) 연산 명령에서는 번지 필드가 없고 명령어(동작 코드)만 존재 무 번지 명령은 스택 구조의 컴퓨터에서 필요 0-주소 형식은 명령어 수가 가장 많이 소요되는 형식 2) 1-주소 형식(one-address instruction) 연산자와 1개의 주소 부분으로 구성 데이터 처리가 누산기(ACC)에서 이루어지며, 결과는 다시 누산기에 저장
3) 2-주소 형식(two-address instruction) 연산자와 2개의 주소 부분(레지스터나 메모리를 지정)으로 구성 실제로 컴퓨터에서 많이 사용 4) 3-주소 형식(three-address instruction) 연산자와 2개의 주소 필드와 연산 결과를 저장하기 위한 1개의 주소 필드로 구성
중앙처리장치 구조 [그림 4-10] 중앙처리장치의 구조
데이터 전송 명령어 레지스터, 주기억장치, 상수 값 구분 (가정) MOV A B 레지스터 또는 주기억장치에 저장된 값을 레지스터 또는 주기억장치로 전송 상수 값을 레지스터 또는 주기억장치로 전송 스택에 저장된 값을 레지스터로 전송 레지스터에 저장된 값을 스택으로 전송 레지스터, 주기억장치, 상수 값 구분 (가정) AX, BX, CX, DX는 레지스터를 의미한다. 30, 100과 같이 숫자로만 이루어진 값은 상수 값을 의미한다. [10], [50]같이 대괄호([, ])로 감싸고 있는 것은 주기억장치를 의미하는데, [10]은 주기억장치의 주소가 10인 부분을 나타낸다. MOV A B B의 값을 A로 전송한다는 뜻으로, A는 주기억장치의 주소와 레지스터가 올 수 있고, B는 레지스터, 주기억장치의 주소, 상수 값이 올 수 있다.
MOV BX [150] 주기억장치 주소 150에 저장된 값을 읽어와 레지스터 BX에 저장 제어장치가 이 명령어를 해독 주소 버스에 150을, 제어 버스에 읽기 제어 신호를 보냄 주기억장치 주소 150에 저장된 500을 데이터 버스를 통해 읽어옴 레지스터 BX에 500을 저장 [그림 4-11] MOV BX [150]의 동작 과정
스택 PUSH AX : 레지스터 AX에 저장된 값을 스택에 삽입 POP BX : 스택에서 데이터 하나를 삭제해 레지스터 BX에 저장
1) 스택(Stack) ■ 삽입(Push)과 삭제(Pop)가 한쪽 끝에서만 수행 되도록 고안된 자료 구조 ■ LIFO(Last In First Out;후입선출) 스택에 저장된 데이터는 가장 마지막에 입력 된 데이터가 가장 먼저 제거되는 구조
■ 삽입, 삭제 알고리즘 ■ 삽입작업 ▶ TOP의 위치 : TOP+1 ▶ 스택의 크기를 넘어서는 경우 오버플로(Overflow)가 발생 →TOP>m ■ 삭제 작업 ▶ TOP의 위치 : TOP-1 ▶ 데이터의 삭제시 Top 포인터가 Bottom 포인터보다 작아지는 경우 언더플로 (Underflow) 가 발생한다. → TOP=BOTTOM ■ 스택 구조의 이용 : 인터럽트 처리, 부 프로그램 분기, 트리에서의 Postorder 운 행, 0-주소 지정 방식, 순환 프로그램(Recursive Program), 컴파일러 등 ■ 삽입, 삭제 알고리즘 삽입 알고리즘 삭제 알고리즘 TOP=TOP+1 IF TOP>m THEN OVERFLOW ELSE X[TOP]←삽입 IF TOP=0 THEN UNDERFLOW ELSE {제거 ← X[TOP] TOP=TOP-1}
3) 큐(Queue) ■ FIFO(First In First Out;선입선출) : 가장 먼저 입력된 데이터가 가장 먼저 제거되는 구조 ■ 한쪽 끝에서만 삽입이 되고, 다른 한쪽 끝에서 삭제가 수행되는 자료 구조 ■ Rear(=Tail) : 가장 최근에 입력된 데이터를 가리키는 삽입 포인터 ■ Front(=Head) : 가장 먼저 삭제될 데이터를 가리키는 삭제 포인터 예) 질서구조, 지하철 표를 사기 ■ 삽입작업 ▶ REAR의 위치 : REAR=REAR+1 ▶ 오버플로(Overflow) 발생 : REAR>m ■ 삭제 작업 ▶ FRONT의 위치 : FRONT=FRONT+1 ▶ 언더플로(Underflow) 발생 : FRONT=0 삽입 알고리즘 삭제 알고리즘 REAR=REAR+1 IF REAR>m THEN OVERFLOW ELSE X[REAR]←삽입 IF FRONT=0 THEN UNDERFLOW ELSE {제거 ← X[FRONT] FRONT=FRONT+1}
입출력 명령어 키보드, 디스크, 모니터 등의 입출력장치와 데이터를 주고받으려면 각 장치의 입출력을 제어하는 제어기를 통해야 하는 것 외에는 주기억장치의 읽기, 쓰기 동작과 거의 유사 IN AX B : 포트 B에서 데이터를 읽어 레지스터 AX에 저장 OUT B AX : 레지스터 AX의 데이터를 포트 B로 출력 [그림 4-15] 입출력장치의 구성
연산 명령어 산술 연산 명령어 산술 연산 명령어, 논리 연산 명령어, 그리고 시프트 명령어로 구분 [표 4-5] 산술 연산 명령어
ADD AX BX 레지스터 AX와 BX에 저장된 값을 더해서 레지스터 AX에 저장
논리 연산 명령어 [표 4-6] 논리 연산 명령어
AND AX BX 레지스터 AX와 BX에 저장된 값을 AND 연산해서 결과를 AX에 저장
시프트 명령어 SHR=Shift Right CIR=Circular Right SHL=Shift Left [표 4-7] 시프트 명령어 SHR=Shift Right CIR=Circular Right SHL=Shift Left
CIR AX 2 레지스터 AX에 저장된 값을 오른쪽으로 2비트 순환 시프트 [그림 4-18] 2비트 순환 시프트 동작
분기 명령어 프로그램 카운터 레지스터 AX와 BX에 저장된 값을 더해서 레지스터 AX에 저장 JUMP나 CALL과 같은 분기 명령어를 이용하면 바로 아래에 위치한 명령어가 아닌 다른 위치의 명령어로 분기 프로그램 카운터 다음에 실행될 명령어가 저장된 주기억장치 주소를 저장 만약 중앙처리장치가 주기억장치 주소 100에 저장된 명령어인 ADD AX BX를 실행하고 있다면 프로그램 카운터에는 다음에 실행될 명령어가 저장된 주소인 101이 저장 [그림 4-20] 프로그램 카운터에는 101이 저장
현재 중앙처리장치는 주소 101에 저장된 명령어를 실행하는 중이므로 프로그램 카운터 값을 1 증가시켜 102로 변경한다. 현재 명령어에 대한 실행을 마치면 프로그램 카운터에 저장된 주소 값인 101에 저장된 명령어인 MOV [201] AX를 읽어와 명령어 레지스터에 저장한다. 현재 중앙처리장치는 주소 101에 저장된 명령어를 실행하는 중이므로 프로그램 카운터 값을 1 증가시켜 102로 변경한다. 다음에 실행될 명령어가 저장되어 있는 주기억장치 주소는 102이기 때문이다. [그림 4-21] 프로그램 카운터값을 1 증가시킴
JUMP 명령어 JUMP 100 C 언어의 goto 문과 같이 임의의 위치로 분기하는 명령어 주기억장치 주소 100로 분기하는 명령어 [그림 4-22] JUMP 100의 동작 과정
CALL 명령어 프로그램 카운터에 저장되어 있는 주소를 스택에 저장하고, 다른 위치로 분기하는 명령어로 함수를 호출할 때 사용 CALL 100 현재 프로그램 카운터에 저장되어 있는 주소를 스택에 삽입하고, 주소 100로 분기하는 명령어 [그림 4-23] CALL 100의 동작 과정
RETURN의 동작 과정 주소 100 ~ 109까지 명령어들을 실행하고, 주소 110의 RETURN을 실행하게 되는데, RETURN은 함수의 끝을 의미하는 것으로, 함수 호출 명령인 CALL 100 다음 주소의 명령어가 실행되도록 한다. 그러므로 RETURN을 실행하면 스텍 포인터 값을 1 감소시킨 주소 20에 저장된 51을 꺼내서 프로그램 카운터에 저장한다. [그림 4-24] RETURN의 동작 과정
주기억장치로부터 두 개의 값을 읽어 와 레지스터에 저장하고, 이 값들을 더한 결과를 주기억장치에 저장하는 프로그램 실행 동작을 살펴보자. 연상 기호 코드 형식
분기 명령어 시작 상태 [그림 4-25] 시작 상태
연상 기호 코드 형식 ① 주소 버스에 프로그램 카운터에 저장된 1을 보내고, 제어 버스에 읽기 제어 신호를 보내 주기억장치 주소 1의 MOV AX [11]을 읽어와 명령어 레지스터에 저장 ② 프로그램 카운터 값을 1 증가시켜 2가 된다. 다음에 실행될 명령어가 저장되어 있는 주기억장치의 주소는 2이기 때문이다. ③ 제어장치는 명령어 레지스터의 내용을 해독하여 주기억장치 주소 11로 부터 데이터를 읽어 올 필요성을 느낀다. ④ 주소 버스에 11을, 제어 버스에 읽기 제어 신호를 보내 주기억장치 주소 11에 저장된 50을 읽어와 레지스터 AX에 저장한다. [그림 4-26] 동작 ①~④
⑤ 다음 명령어를 실행하기 위해 프로그램 카운터에 저장된 2를 주소 버스를 통해 보내고, 읽기 제어 신호를 보내 주소 2에 저장된 MOV BX [12]를 읽어와 명령어 레지스터에 저장한다 ⑥ ②~④와 유사한 동작을 거쳐 프로그램 카운터는 3이 되고 레지스터 BX에는 30이 저장된다. 주소 2 명령어에 대한 실행이 끝났다. [그림 4-27] 동작 ⑤~⑥
⑦ 다음 명령어인 주기억장치 주소 3에 저장된 ADD AX BX를 읽어와 명령어 레지스터에 저장한다 ⑧ 제어장치는 명령어 레지스터에 저장된 명령어를 해독하여 레지스터 AX의 50과 레지스터 BX의 30을 연산장치로 전송하여 제어장치의 지시에 의해 연산장치는 이 두 값을 더해 결과인 80을 레지스터 AX에 저장한다. 주소 3 명령어에 대한 실행이 끝났다. [그림 4-28] 동작 ⑦~⑧
⑨ 주소 4에 저장된 MOV [13] AX를 읽어와 명령어 레지스터에 저장하고, 프로그램 카운터 값을 1 증가시켜 5가 된다. ⑪ 다음 명령어인 주소 5에 저장된 HALT를 읽어와 명령어 레지스터에 저장하고, 프로그램 카운터 값을 1 증가시켜 6이 된다. ⑫ 제어장치가 명령어를 해독하여 프로그램 실행을 종료한다. [그림 4-29] 동작 ⑨~⑩
2진 표기법 형식 2진 표기법 형식의 명령어를 살펴보기 위해 다음과 같이 가정한다. 주기억장치는 바이트 단위로 분할하며 0부터 15까지 16개의 주소를 갖는다. 범용 레지스터는 4개로 각 번호는 00, 01, 10, 11이다. 명령어의 길이는 8비트로 처음 2비트는 명령코드고, 다음 2비트는 피연산자1 부분, 나머지 4비트는 피연산자2 부분이다. [그림 4-30] 8비트 크기의 데이터 버스
명령어
명령어 1행은 주기억장치 주소 11의 내용을 레지스터 0 로 읽어오는 명령어 2행은 주기억장치 주소 12의 내용을 레지스터 1로 읽어오는 명령어 3행은 레지스터 0과 1에 저장된 값을 더한 결과를 레지스터 0에 저장하는 명령어 4행은 레지스터 0의 내용을 주기억장치 주소 13에 저장하는 명령어 5행은 프로그램을 종료하는 명령어 00 = 주 기억 →레지스터 01= 레지스터 → 주 기억 10= 레지스터 연산 후 저장 11 = 프로그램 종료
시작 상태 [그림 4-31] 시작 상태
주소 버스에 프로그램 카운터에 저장된 0001을 보내고 읽기 제어 신호를 보내면 주소 1에 저장된 내용이 데이터버스를 통해 전송되어 명령어 레지스터에 저장됨 프로그램 카운터가 1 증가하여 2가 된다. 제어장치가 명령어 레지스터에 저장된 명령어를 해독하여 주기억장치 주소 11의 내용을 읽어와 범용 레지스터 00에 저장한다. 그러면 주소 1 명령어에 대한 실행이 끝난다. [그림 4-32] 주소 1 명령어에 대한 동작
명령어와 데이터가 16비트인 경우의 구조 [그림 4-3] 주소 1 명령어에 대한 동작