강민철님의 "혼자 공부하는 컴퓨터 구조+운영체제"을 기반으로 학습한 게시물입니다.
📕 목차
1. ALU와 제어장치
2. Register
3. 명령어 사이클과 인터럽트
![](https://blog.kakaocdn.net/dn/tQeOF/btsmPAZ9qUE/Rwg4ii9zw9NVXKM2ELFhoK/img.png)
1. ALU와 제어장치
📌 ALU
- ALU는 연산한 결괏값과 플래그(flag)를 내보낸다. (플래그 레지스터에 저장)
- Register를 통해 피연산자를 받고, 제어장치로부터 제어 신호를 받아 수행할 연산을 판단
- 결괏값은 바로 Memory에 저장되지 않고 일시적으로 Register에 저장 (CPU가 Memory에 접근하는 게 느려서)
- 가산기, 보수기, 시프터, 오버플로우 검출기 등의 회로가 내부에 구성
✒️ 플래그(flag)
종류 의미 예시 sign flag 연산 결과의 부호 • 음수 : 1
• 양수 : 0zero flag 연산 결과 0 여부 • 0인 경우 : 1
• 0이 아닌 경우 : 0carry flag 연산 결과 올림수나 빌림수 발생 여부 • 발생 : 1
• 미발생 : 0overflow flag 오버 플로우 발생 여부 • 발생 : 1
• 미발생 : 0interrupt flag 인터럽트 가능 여부 • 가능 : 1
• 불가능 : 0supervisor flag 커널 모드 / 사용자 모드 • 커널 모드 : 1
• 사용자 모드 : 0
📌 제어장치
- CPU 구성 요소 중 가장 정교하게 설계된 부분
- 4가지 수신 정보
- 클럭(clock) 신호 수신
- 명령어 Register로부터 해석해야 할 명령어 수신
- Flag register의 flag 수신
- 제어 버에서 제어 장치로 전달된 제어 신호 수신
- 2가지 출력 정보
- 내부 제어 신호 출력 (Register, ALU)
- Register : 레지스터 간 데이터 이동, 저장된 명령어 해석
- ALU : 수행할 연산 지시
- 외부 제어 신호 출력
- Memory : 메모리 값 읽기/쓰기
- IO Device(보조 기억 장치) : IO 장치 값 읽기/쓰기
- 내부 제어 신호 출력 (Register, ALU)
2. Register
- 프로세서(CPU)에 위치한 고속의 메모리
- 특수한 값 하나를 저장하는 기억공간
- 프로그램 속 명령어와 데이터는 실행 전후로 반드시 레지스터에 저장
📌 Register 종류
- 프로그램 카운터 (Program Counter)
- 메모리에서 가져올 명령어 주소 저장
- 명령어 포인터(IP; Instruction Pointer)라고도 함
- 명령어 레지스터 (Instruction Register)
- 메모리에서 읽어 들인 명령어를 저장
- 제어장치에서 명령어 레지스터의 명령어를 수신하여 해석한 뒤 제어신호 출력
- 메모리 주소 레지스터 (MAR; Memory Address Register)
- 메모리의 주소를 저장
- CPU가 주소 버스로 내보낼 값
- 메모리 버퍼 레지스터 (MBR; Memory Buffer Register)
- 메모리와 주고받을 값(데이터, 명령어) 저장
- CPU가 데이터 버스로 주고받을 값
- 메모리 데이터 레지스터(MDR; Memory Data Register)와 동일
- 플래그 레지스터 (Flag Register)
- ALU 연산 결과 또는 CPU 상태에 대한 부가적인 정보 저장
- 범용 레지스터 (General Purpose Register)
- 다양하고 일반적인 상황에서 자유롭게 사용
- 데이터와 주소를 모두 저장 가능
- CPU 내에 여러 개의 범용 레지스터들이 존재
- 스택 포인터 (Stack Pointer)
- 스택의 꼭대기를 가리키는 레지스터
- 스택 주소 지정 방식 사용
- 베이스 레지스터 (Base Register)
- 기준 주소를 의미
- 오퍼랜드(기준 주소로부터 떨어진 거리)와 함께 사용하여 베이스 레지스터 주소 지정 방식 사용
✒️ 1~4번 레지스터 동작 과정
1️⃣ CPU로 실행할 프로그램이 1000~1500번지까지 저장되어 있음
![](https://blog.kakaocdn.net/dn/ctvv1t/btsmOosje7Z/byOd3tdUGd1xMk8cnLunr0/img.png)
2️⃣ 프로그램 실행을 위해 프로그램 카운터에 1000번지 저장
![](https://blog.kakaocdn.net/dn/Dks6A/btsmQrhnFvc/eJPm1gpQlSymlxNsZOWWsk/img.png)
3️⃣ 주소 버스로 1000번지를 보내기 위해 메모리 주소 레지스터에 1000번지 저장
![](https://blog.kakaocdn.net/dn/cTxtGb/btsmOT0gOKX/5be8O9owYWqRlJkJLs5AxK/img.png)
4️⃣ '메모리 읽기' 제어신호화 메모리 주소 레지스터 값이 각각 제어 버스와 주소 버스를 통해 메모리로 전달
![](https://blog.kakaocdn.net/dn/m9NE0/btsmN3aXtf4/MCWHJskjkScHAr5j47oF0k/img.png)
5️⃣ 메모리 1000번지 주소의 값이 데이터 버스를 통해 메모리 버퍼 레지스터에 저장
![](https://blog.kakaocdn.net/dn/cYi0yh/btsmOUSs0nF/6A8YWKryMFVIy5GikHDYbK/img.png)
- 이 때, 프로그램 카운터가 증가하여 다음 명령어를 읽을 준비를 한다.
6️⃣ 메모리 버퍼 레지스터에 저장된 값이 명령어 레지스터로 이동
![](https://blog.kakaocdn.net/dn/5Eik6/btsmRrA1DYP/Bx1oypaKiCkYbNHKXPr9bk/img.png)
7️⃣ 제어장치가 명령어 레지스터의 명령어를 해석하고 제어 신호 발생
![](https://blog.kakaocdn.net/dn/R92xQ/btsmPAlAWse/4O3EEWVkkft9qfK6g8A9J1/img.png)
✒️ 순차적 실행 흐름이 끊기는 경우
명령어 중 JUMP, CONDITIONAL JUMP, CALL, RET처럼 특정 Memory 주소로 실행 흐름을 이동하는 명령어 실행 시, 프로그램이 순차적으로 실행되지 않는다.
또한 Interrupt가 발생해도 순차적인 흐름은 끊어진다.
📌 스택 주소 지정 방식(Stack addressing mode)
- Stack point register가 Stack 꼭대기 주소 정보를 가리킨다
- Stack 영역 : 메모리 안에서 Stack처럼 사용할 영역 (다른 주소 공간과 다르게 사용하기로 암묵적 약속)
📌 변위 주소 지정 방식(Displacement addressing mode)
- 프로그램 카운터와 베이스 레지스터 사용
- 명령어(연산 코드 + 오퍼랜드)에서 오퍼랜드 필드 값(변위)과 특정 Register 값을 더하여 유효 주소 판단
- (레지스터 값 + 오퍼랜드)가 가리키는 주소의 값으로 (연산 코드) 수행
1️⃣ 상대 주소 지정 방식(relative addressing mode)
- 오퍼랜드와 프로그램 카운터 값을 더하여 유효주소 판단
- 읽어 들일 명령어 주소(프로그램 카운터)에서 이동 값(변위)을 더한 메모리 주소 값에 접근
2️⃣ 베이스 레지스터 주소 지정 방식(base-register addressing mode)
- 오퍼랜드와 베이스 레지스터 값을 더하여 유효주소 판단
3. 명령어 사이클과 인터럽트
- CPU가 하나의 명령어를 처리하는 과정에는 정해진 흐름이 있다.
- 명령어 사이클 : 하나의 명령어를 처리하는 정형화된 흐름
- 인터럽트 : 정해진 흐름이 끊어지는 상황
📌 명령어 사이클(instruction cycle)
- 프로그램 속 각각의 명령어들이 반복되며 실행되는 일정한 주기
- 인출 사이클(fetch cycle)
- 메모리에 있는 명령어를 CPU로 가지고 오는 단계
- 실행 사이클(execution cycle)
- CPU로 가져온 명령어를 실행하는 단계
- 제어장치가 명령어 레지스터에 담긴 값을 해석, 제어 신호 발생
- 간접 사이클(indirect cycle)
- 명령어 실행을 위해 메모리 접근을 한 번 더 해야 하는 경우
- 간접 주소 지정 방식의 경우 오퍼랜드 필드에 유효 주소의 주소를 명시해둠
- 즉, 명령어를 인출하여 CPU를 가져와도 바로 실행 사이클 돌입 불가능
📌 인터럽트(interrupt)
- CPU가 수행 중인 작업을 잠시 방해하고, 다른 일을 처리시킨다.
- 동기 인터럽트(synchronous interrupts)
- CPU에 의해 발생
- 명령어 수행 도중 예상치 못한 상황
- 예외(exception)과 동일
- 비동기 인터럽트(asynchronous interrupts)
- 입출력 장치에 의해 발생
- ex. CPU가 프린터같은 IO 장치에 작업을 요청하고, 작업이 끝낸 IO 장치가 CPU에 완료 알림(인터럽트) 송신
- ex. 키보드, 마우스 같은 IO 장치가 어떤 입력을 받으면 이를 처리하기 위해 CPU에 입력 알림(인터럽트) 송신
- 하드웨어 인터럽트와 동일
📌 하드웨어 인터럽트
💡 CPU가 Interrupt를 처리하는 것은 ISR을 실행하고, 본래 작업으로 돌아오는 것이다.
- CPU 입출력 작업 도중에도 효율적 명령어 처리를 위한 알림과 같은 인터럽트
- IO 장치는 일반적으로 cpu보다 속도가 현저히 느림
- HW가 인터럽트를 사용하지 않으면, CPU가 주기적으로 작업 완료 여부 확인 과정 필요 (오버헤드)
- 일반적인 처리 순서
- IO 장치는 CPU에 인터럽트 요청 신호 송신
- CPU가 실행 사이클이 끝나고 명령어 인출하기 전 항상 인터럽트 여부 확인
- CPU가 인터럽트 요청 확인 → 인터럽트 플래그를 통해 현재 인터럽트 수신 가능 여부 확인
- 가능하다면 CPU는 지금까지 작업을 백업
- 프로그램 카운터 값 등 현재 프로그램 재개를 위한 모든 내용을 Stack에 백업
- CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴 실행
- 루틴이 종료되면 백업해둔 작업을 복구하여 재실행
- 용어 정리
- 인터럽트 요청 신호
- CPU에 작업 중단 가능 여부 확인
- 인터럽트 플래그
- Flag Register의 Interrupt flag 활성화되어 있다면 인터럽트 가능 (비활성화면 인터럽트 무시)
- 막을 수 있는 인터럽트(maskable interrupt) : 일반적인 IO 장치 요청
- 막을 수 없는 인터럽트(non maskable interrupt) : 정전이나 하드웨어 고장으로 인한 인터럽트
- 인터럽트 서비스 루틴 (ISR; Interrupt Service Routine)
- 인터럽트 핸들러(Interrupt Handler)와 동일
- 해당 Interrupt를 어떻게 처리하고 작동해야 할지에 대한 정보로 이루어진 Program
- Memory에는 여러 개의 Interrupt Service Routine이 저장되어 있고, 하나하나가 Interrupt에 대한 대처 방식을 정의해둠 (명령어 + 데이터)
- 인터럽트 벡터(Interrupt Vecotr)
- CPU가 수많은 ISR을 구분하기 위한 정보
- ISR의 시작 주소를 통해, Interrupt가 발생하면 해당 주소로 jump한다.
- 인터럽트 요청 신호
📌 예외 종류
Exception이 발생하면 CPU는 하던 일을 중단하고 예외를 처리한다.
예외를 처리하면 cpu는 본래 작업으로 되돌아 오는데, 어디로 돌아가느냐로 나뉘어질 수 있다.
Synchronous Interrupts는 4가지로 더 나누어 볼 수 있다.
- 폴트(fault)
- 예외를 처리한 직후 예외가 발생한 명령어부터 실행 재개
- ex. 프로그램 실행에 필요한 데이터가 Memory에는 없고 보조 기억 장치에만 있는 경우, CPU는 fault를 발생시키고 보조 기억 장치에서 데이터를 Memory로 옮긴 후, fault가 발생한 명령어부터 실행
- 트랩(trap)
- 예외를 처리한 직후 예외가 발생한 명령어의 다음 명령어부터 실행 재개
- 주로 디버깅할 때 사용
- 중단(abort)
- CPU가 프로세스를 강제로 중단시킬 정도로 심각한 오류가 검출된 경우
- 소프트웨어 인터럽트(software interrupt)
- 시스템 호출이 발생했을 때 발생