Chapter 04 CPU의 작동 원리
1. ALU와 제어장치
Key Word: ALU / 플래그 / 제어장치 / 제어 신호
CPU(01장)
- 메모리에 저장된 명령어 읽어 들이고, 해석하고, 실행하는 장치
- ALU(계산 담당)/ 제어장치(명령어 읽어 들이고 해석)/ 레지스터(작은 임시 저장 장치)
ALU
- 계산하는 부품 => 계산 하기 위해서는 피연산자, 수행할 연산자 필요
- 계산한 결괏값과 플래그 내보냄
<받아들이는 정보>
- 레지스터 ~> 피연산자 받아들임 + 제어장치 ~> 수행할 연산 알려주는 제어 신호 받아들임
-> 피연산자 + 제어 신호 -> 산술 연산, 논리 연산 등 다양한 연산 수행
<내보내는 정보>
- 연산을 수행한 결과(특정 숫자/ 문자/ 메모리 주소) -> 바로 메모리에 저장 X 일시적으로 레지스터에 저장
- ALU의 결괏값을 메모리가 아닌 레지스터에 우선 저장
- CPU가 메모리에 접근하는 속도 < 레지스터에 접근하는 속도
- IF. ALU가 연산할 때마다 결과 메모리에 저장 -> CPU가 메모리에 접근 ↑ -> CPU가 프로그램 속도 ↓
- 플래그(flag)
- 이진수만 봐서 음수/양수 판단 어려움 -> 구분 위해 플래그 사용(02장)
- 연산 결과에 대한 추가적인 상태 정보
- CPU가 프로그램을 실행하는 도중 반드시 기억해야 하는 일종의 참고 정보
오버플로우(overflow): 연산 결과가 연산 결과를 담을 레지스터보다 큰 상황
<플래그 종류>
종류 | 의미 | 사용 예시(계산 결과) |
부호 플래그 | 연산한 결과의 부호 | 1: 음수 / 0: 양수 |
제로 플래그 | 연산 결과가 0인지 여부 | 1: 0 / 0: 0 아님 |
캐리 플래그 | 연산 결과 올림수/내림수 발생했는지 | 1: 발생 / 0: 발생 X |
오버플로우 플래그 | 오버플로우 발생했는지 | 1: 발생 / 0: 발생 X |
인터럽트 플래그 | 인터럽트 가능한지 | 1: 가능 / 0: 불가능 |
슈퍼바이저 플래그 | 커널 모드/사용자 모드 실행 중인지 | 1: 커널(관리자) / 0: 사용자 |
플래그 레지스터
- 플래그 값(0/1) 저장
- 플래그 레지스터 읽으면 연산 결과에 대한 추가적인 정보, 참고 정보 얻을 수 있음
ALU가 연산 수행한 직후 부호 플래그 1 -> 연산 결과: 음수
ALU가 연산 수행한 직후 제로 플래그 1 -> 연산 결과 0
이 밖에도 ALU 내부에 여러 계산을 위한 회로 존재
ex. 가산기(덧셈), 보수기(뺄셈), 시프터(시프트 연산), 오버플로우 검출기(오버플로우 대비) 등
제어장치
- 제어 신호를 내보내고, 명령어를 해석하는 부품
- 제어 신호: 컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호
- CPU 구성 요소 중 가장 정교하게 설계된 부품
- 제조사마다 구현 방식, 명령어 해석하는 방식, 받아들이고 내보내는 정보 차이 O
<받아들이는 정보>
- 클럭(clock) 신호 받아들임
- 클럭: 컴퓨터의 모든 부품을 일사불란하게 움직일 수 있게 하는 시간 단위
- 클럭의 '똑-딱-똑-딱' 주기에 맞춰
-> 한 레지스터가 다른 레지스터로 데이터 이동/ ALU에서 연산 수행/ CPU가 메모리에 저장된 명령어 읽어들임 - 컴퓨터의 모든 부품이 클럭 신호에 맞춰 작동 != 컴퓨터의 모든 부품이 한 클럭마다 작동
- 클럭이라는 박자에 맞춰 작동할 뿐 한 박자마다 작동하는 것 X
- 하나의 명령어가 여러 클럭에 걸쳐 실행 가능
- '해석해야 할 명령어' 받아들임
- CPU가 해석해야 할 명령어 -> 명령어 레지스터에 저장
- 제어장치) 레지스터로부터 해석할 명령어 받아들이고 해석
-> 제어 신호 발생시켜 컴퓨터 부폼들에 수행해야 할 내용 알려줌
- 플래그 레지스터 속 플래그 값 받아들임
- 플래그: ALU 연산에 대한 추가적인 상태 정보
- 제어장치) 제어 신호 ~> 컴퓨터 부품 제어 시 중요한 참고 사항 무시 X
=> 제어장치) 플래그 값 받아들이고 참고하여 제어 신호 발생시킴
- 시스템 버스, 그중에서 제어 버스로 전달된 제어 신호 받아들임
- 제어 신호는 CPU뿐만 아니라 입출력장치 비롯한 CPU 외부 장치도 제어 신호 발생시킬 수 O
- 제어장치) 제어 버스 ~> 외부로부터 전달된 제어 신호 받아들이기도 함
=> 제어장치는 클럭, 현재 수행할 명령어, 플래그, 제어 신호 받아들임
<내보내는 정보>
- CPU 외부에 전달하는 제어 신호
- 제어 버스로 제어 신호를 내보냄
- 메모리에 전달하는 제어 신호
- 입출력장치(보조기억장치)에 전달하는 제어 신호
- CPU 내부에 전달하는 제어 신호
- ALU에 전달하는 제어 신호
- 수행할 연산 지시
- 레지스터에 전달하는 제어 신호
- 레지스터 간 데이터 이동 or 레지스터에 저장된 명령어 해석
- ALU에 전달하는 제어 신호
=> 제어장치는 CPU 내부/외부로 제어 신호 내보냄
(제어장치)
- 메모리에 저장된 값을 읽거나 메모리에 새로운 값 쓰고 싶음 -> 메모리로 제어 신호 내보냄
- 입출력장치의 값을 읽거나 새로운 값 쓰고 싶음 -> 입출력장치로 제어 신호 내보냄
2. 레지스터
Key Word: 프로그램 카운터 / 명령어 레지스터 / 메모리 주소.버퍼 레지스터
/ 범용.플래그 레지스터 / 스택 포인터 / 베이스 레지스터
레지스터 내부에서 맴돌아서 사라지지 않게 해야함
프로그램 속 명령어와 데이터는 실행 전후로 반드시 레지스터에 저장
-> 레지스터에 저장된 값 잘 관찰 => 프로그램의 실행 흐름 파악 가능
반드시 알아야 할 레지스터
<알아야 할 8개의 레지스터>
- 프로그램 카운터
- 명령어 레지스터
- 메모리 주소 레지스터
- 메모리 버퍼 레지스터
- 플래그 레지스터
- 범용 레지스터
- 스택 포인터
- 베이스 레지스터
*CPU 종류마다 레지스터 종류 다름
프로그램 카운터(PC; Program Counter) = 명령어 포인터(IP; Instruction Pointer)
- 메모리에서 가져올 명령어의 주소(메모리에서 읽어 들일 명령어의 주소) 저장
- 자동으로 1씩 증가
명령어 레지스터(IR; Instruction Register)
- 해석할 명령어(방금 메모리에서 읽어 들인 명령어) 저장
- 제어장치) 명령어 레지스터 속 명령어 받아들이고 해석 -> 제어 신호 내보냄
메모리 주소 레지스터(MAR; Memory Address Register)
- 메모리의 주소를 저장
- (CPU가 읽어 들이고자 하는 주소 값 -> 주소 버스) => 메모리 주소 레지스터 거침
메모리 버퍼 레지스터(MBR; Memory Buffer Register) = 메모리 데이터 레지스터(MDR; Memory Data Register)
- 메모리와 주고받을 값(데이터와 명령어) 저장하는 레지스터
- (데이터 버스로 주고 받을 값 = 메모리에 쓰고 싶은 값 or 메모리부터 전달받은 값) => 메모리 버퍼 레지스터 거침
CPU로 실행할 프로그램이 1000번지 ~ 1500번지 저장, 1000번지에는 $1101_{(2)}$ 저장
(가정: 프로그램을 이루는 명령어들은 각각 하나의 메모리 번지 차지)
1. 프로그램 처음 실행 -> (프로그램 카운터) 1000 저장
= 메모리에서 가져올 명령어 1000번지에 있음
2. 1000번지 읽어 들이기 위해서는 (주소 버스)로 1000번지 내보내야 함
-> (메모리 주소 레지스터)에 1000이 저장
3. 제어장치 -(제어 버스) 메모리 읽기-> (메모리)
+ (메모리 주소 레지스터) -(주소 버스) 메모리 주소: 1000번지-> (메모리) 1000번지
4. (메모리) 1000번지에 저장된 값 1101 -(데이터 버스)-> (메모리 버퍼 레지스터) 1101
/ (프로그램 카운터) 증가 -> 다음 명령어 읽을 준비
5. (메모리 버퍼 레지스터)에 저장된 값 1001 -> (명령어 레지스터)로 이동 1101
6. (제어장치) 명령어 레지스터의 명령어 해석, 제어 신호 발생
프로그램 카운터 지속적으로 증가, 다음 명령어 읽어 들일 준비
-> 반복되면서 CPU 프로그램 차례대로 실행
=> CPU가 메모리 속 프로그램 순차적으로 읽어 들이고 실행해 나갈 수 있는 이유
: CPU 속 프로그램 카운터가 꾸준히 증가하기 때문
<순차적인 실행 흐름이 끊기는 경우>
프로그램 카운터 꾸준히 증가, 프로그램 차례대로 실행
But, 종종 프로그램 카운터가 실행 중인 명령어의 다음 번주 주소 X 전혀 다른 값으로 업데이트 되는 경우 O
-> 프로그램 차례대로 실행 X
Q: 이런 상황 언제 발생?
A: 특정 메모리 주소로 실행 흐름을 이동하는 명령어(UMP, CONDITIONAL JUMP, CALL, RET) 실행
-> 프로그램 차례대로 실행 X, 프로그램 카운터에는 변경된 주소가 발생
IF. 1200번지 실행 중 JUMP 2500(2500번지로 점프 == 2500번지부터 실행)
-> 명령어 실행 다음에는 1201번지가 아닌 2500번지 실행해야 함
+ 인터럽트가 발생해도 프로그램의 순차적인 실행 흐름 끊어짐
+ CONDITIONAL JUMP/ COMPARE 조건 보고 JUMP
플래그 레지스터(flag register)
- ALU 연산 결과에 따른 플래그를 저장
- 연산 결과 or CPU 상태에 대한 부가적인 정보를 저장
범용 레지스터(general purpose register)
- 다양하고 일반적인 상황에서 자유롭게 사용할 수 있음
- 데이터와 주소 모두 저장
- 메모리 버퍼 레지스터: 데이터 버스로 주고받을 값만 저장
- 메모리 주소 레지스터: 주소 버스로 보낼 주소값만 저장
- CPU안에 여러 개의 범용 레지스터 있고, 현재 대다수 CPU는 모두 범용 레지스터 가짐
특정 레지스터를 이용한 주소 지정 방식(1)
스택 주소 지정 방식
스택과 스택 포인터를 이용한 주소 지정 방식
- 스택: 한쪽 끝이 막혀 있는 통과 같은 저장 공간
- 가장 최근에 저장하는 값부터 꺼낼 수 있음
- 메모리 안에 있음
- 스택 포인터(stack pointer)
- 스택의 꼭대기를 가리키는 레지스터
- 스택에 마지막으로 저장한 값의 위치를 저장하는 레지스터
- 스택의 어디까지 데이터가 채워져 있는지에 대한 표시
스택 포인터: 꼭대기 주소(4번지) 저장 == 스택 포인터가 스택의 꼭대기를 가리키고 있음
1 ~ 3번지(데이터 X), 4번지(데이터 1), 5번지(데이터 2), 6번지(데이터 3)
스택에서 데이터 꺼낼 때 1 -> 2 -> 3 순서대로 데이터 꺼냄
1 꺼냄 => 스택에 2, 3이 남음 + 스택의 꼭대기 주소 변경(4 -> 5번지) => (스택 포인터) 5번지 가리킴 가리킴
4 추가 => 스택의 꼭대기(4번지)에 4 저장, 스택의 꼭대기 주소 변경(5 -> 4번지) => (스택 포인터) 4번지 가리킴
스택 영역
- 메모리 안에 스택처럼 사용할 영역
- 주소 공간과는 다르게 스택처럼 사용하기로 암묵적으로 약속된 영역
특정 레지스터를 이용한 주소 지정 방식(2)
명령어 = 연산코드 + 오퍼랜드(03장)
오퍼랜드 필드에는 메모리의 주소가 담길 때도 있음
변위 주소 지정 방식(displacement addressing mode)
- 오퍼랜드 필드의 값(변위) + 특정 레지스터의 값 -> 유효 주소 얻어냄
- 변위 주소 지정 방식을 사용하는 명령어
- 연산 코드 필드 + 레지스터 필드 + 오퍼랜드 필드
- 오퍼랜드 필드의 주소, 어떤 레지스터를 더하는지
- 상대 주소 지정 방식(relative addressing mode)
- 오퍼랜드 + 프로그램 카운터의 값 -> 유효 주소 얻는 방식
- (프로그램 카운터) 읽어 들일 명령어 주소 저장
IF. 오퍼랜드: 음수(-3) -> (CPU) 읽어 들이기로 한 명령어부터 3번째 이전 번지로 접근
= 실행하려는 명령어의 3칸 이전 번지 명령어 실행
vs. 오퍼랜드: 양수(3) -> (CPU) 읽어 들이기로 한 명령어의 3번째 이후 번지로 접근
= 실행하려는 명령어에서 3칸 건너뛴 번지 실행 - 모든 코드 실행 X, 분기하여 특정 주소의 코드 실행할 때 사용(~= if문)
- 베이스 레지스터 주소 지정 방식(base-register addressing mode)
- 오퍼랜드 + 베이스 레지스터의 값 -> 유효 주소를 얻는 방식
오퍼랜드: 기준 주소로부터 떨어진 거리/ 베이스 레지스터: 기준 주소 - 베이스 레지스터 속 기준 주소로부터 얼마나 떨어져 있는 주소에 접근할 것인지 연산 -> 유효 주소
- ex. (베이스 레지스터) 200, (오퍼랜드) 40 == 기준 주소 200번지로부터 40만큼 떨어진 240번지로 접근
- 오퍼랜드 + 베이스 레지스터의 값 -> 유효 주소를 얻는 방식
- 상대 주소 지정 방식(relative addressing mode)
3. 명령어 사이클과 인터럽트
Key Word: 명령어 사이클 / 인터럽트 / 예외 / 하드웨어 인터럽트 / 인터럽트 서비스 루틴
CPU가 하나의 명령어를 처리하는 과정
: 어떤 정해진 흐름 존재, CPU는 그 흐름을 반복하여 명령어 처리
명령어 사이클: 하나의 명령어를 처리하는 정형화된 흐름
간혹, 흐름이 끊어지는 상황 발생: 인터럽트
명령어 사이클 (instruction cycle)
- 프로그램 속 각각의 명령어들이 실행 될 때 반복되는 주기
- 프로그램 속 각각의 명령어들은 명령어 사이클이 반복되며 실행
- 하나의 명령어가 처리되는 주기/ 인출, 실행, 간접, 인터럽트 사이클로 구성
- 인출 사이클(fetch cycle)
- 메모리에 있는 명령어 -> CPU로 가지고 오는 단계
- 실행 사이클(execution cycle)
- CPU로 가져온 명령어를 실행하는 단계
- (제어장치) 명령어 레지스터에 담긴 값 해석, 제어 신호 발생
- 간접 사이클(indirect cycle)
- 명령어를 실행하기 위해 메모리 접근을 더 함
=> 인출, 실행 사이클/ 인출, 간접, 실행 사이클 거쳐 실행
인터럽트(interrupt)
- 방해하다, 중단시키다
- CPU의 (정상적인) 작업을 방해하는 신호
- ex. CPU가 꼭 주목해야 할 때/ CPU가 빠르게 처리해야 할 다른 작업이 생겼을 때
- CPU가 인터럽트 처리 == 인터럽트 서비스 루틴 실행 -> 본래 수행하던 작업으로 다시 되돌아옴
- 동기 인터럽트(synchronous interrupts) = 예외(exception) 인터럽트
- CPU에 의해 발생하는 인터럽트
- CPU가 명령어들을 수행하다가 예상치 못한 상황에 마주쳤을 때
- ex. CPU가 실행하는 프로그래밍상의 오류
- 서로가 서로의 정보를 앎
- 비동기 인터럽트(asynchronous interrupts) = 하드웨어 인터럽트
- 입출력장치에 의해 발생하는 인터럽트
- ex. 세탁기 완료 알림, 전자레인지 조리 완료 알림과 같은 알림 역할
- 서로가 서로의 정보를 모름
- CPU) 입출력 작업 도중에도 효율적으로 명령어 처리 -> 알림과 같은 하드웨어 인터럽트 사용
=> 인터럽트 X -> CPU) 주기적으로 완료 여부 확인해야 함(= 동기)
/ 입출력장치 < CPU 속도
- 입출력장치(프린터)에 입출력 작업 부탁 -> 작업 끝낸 입출력장치가 CPU에 완료 알림(인터럽트) 보냄
- 입출력장치(키보드, 마우스)가 어떤 입력 받아들임 -> 처리 위해 CPU에 입력 알림(인터럽트) 보냄
- 처리 순서
- 입출력장치) 인터럽트 요청 신호 -> CPU
인터럽트 요청 신호: CPU 작업을 방해하는 인터럽트에 대한 요청 - CPU) 실행 사이클 끝나고 명령어 인출하기 전 항상 인터럽트 여부 확인
- CPU) 인터럽트 요청 확인, 인터럽트 플래그 ~> 현재 인터럽트 받아들일 수 있는지 여부 확인
인터럽트 플래그: 인터럽트 요청 신호 받아들일지 무시할지 결정하는 비트(1: 가능/ 0: 불가능)- 불가능 -> CPU) 인터럽트 요청이 오더라도 해당 요청 무시 But, 무시 X 인터럽트 O
- 가능 -> CPU) 인터럽트 요청 신호 받아들이고 처리
- 인터럽트 받아들일 수 O -> CPU) 지금까지 작업 백업
- CPU) 인터럽트 벡터 참조 -> 인터럽트 서비스 루틴 실행
인터럽트 서비스 루틴(= 인터럽트 핸들러): 인터럽트 처리하는 프로그램
/ 인터럽트 벡터: 인터럽트 서비스 루틴을 식별하기 위한 정보
=> 인터럽트 벡터를 알면 인터럽트 서비스 루틴의 시작 주소를 알 수 있음 - 인터럽트 서비스 루틴 실행 끝 -> 4에서 백업해 둔 작업 복구하여 실행 재개
- 입출력장치) 인터럽트 요청 신호 -> CPU
*모든 인터럽트를 막을 수 있는 것은 X
+예외의 종류
인터럽트
- 동기 인터럽트(예외)
- 폴트
- 트랩
- 중단
- 소프트웨어 인터럽트
- 비동기 인터럽트(하드웨어 인터럽트)
예외 발생 -> CPU 하던 일 중단, 해당 예외 처리
-> 본래 하던 작업으로 되돌아와 실행 재개
=> 예외가 발생한 명령어부터 실행 or 예외가 발생한 명령어의 다음 명령어부터 실행
-> 폴트 / 트랩으로 나뉨
폴트(fault)
예외를 처리한 직후 예외가 발생한 명령어부터 실행 재개하는 예외
CPU가 한 명령어 실행하려 함
명령어 실행하기 위한 꼭 필요한 데이터가 메모리에 X 보조기억장치에 O
But, 프로그램이 실행되려면 반드시 메모리에 저장되어 있어야 함
-> CPU 폴트 발생 => 보조기억장치로부터 필요한 데이터를 메모리로 가져와 저장
트랩(trap)
- 예외를 처리한 직후 예외가 발생한 명령어의 다음 명령어부터 실행 재개하는 예외
- 주로 디버깅할 때 사용
- 디버깅 할 때 특정 코드가 실행되는 순간 프로그램의 실행 멈추게 할 수 있음
- 이 코드가 실행된 그 순간의 프로그램의 상태 보기 -> 코드가 실행되는 순간 실행 멈추기
디버깅(debugging): 프로그램 개발 중에 발생한 문제를 진단하고 해결하기 위한 작업 의미
중단(abort)
CPU가 실행 중인 프로그램을 강제로 중단시킬 수밖에 없는 심각한 오류 발견했을 때 발생하는 예외
소프트웨어 인터럽트(software interrupt)
시스템 호출이 발생했을 때 나타남
출처
'Computer Science > 컴퓨터구조 | 운영체제' 카테고리의 다른 글
[혼자 공부하는 컴퓨터구조+운영체제] Chapter 06 메모리와 캐시 메모리 (0) | 2024.01.08 |
---|---|
[혼자 공부하는 컴퓨터구조+운영체제] Chapter 05 CPU 성능 향상 기법 (0) | 2024.01.08 |
[혼자 공부하는 컴퓨터구조+운영체제] Chapter 03 명령어 (0) | 2024.01.05 |
[혼자 공부하는 컴퓨터구조+운영체제] Chapter 02 데이터 (0) | 2024.01.05 |
[혼자 공부하는 컴퓨터구조+운영체제] Chapter 01 컴퓨터 구조 시작하기 (0) | 2024.01.05 |