본 게시물은 ‘강민철, ⌜혼자 공부하는 컴퓨터구조 + 운영체제⌟, 한빛미디어, 2022’ 을 인용하였습니다.
1. 소스코드와 명령어
고급 언어&저급 언어
- 고급 언어(high-level programming language) : 컴퓨터 이해X, 사람 이해O
- C, C++, Java, Python 등 프로그래밍 언어
- 저급 언어(low-level programming language) : 컴퓨터 이해/실행O
- 종류
- 기계어(machine code) : 0과 1의 명령어 비트로 이루어진 언어로 오로지 컴퓨터만을 위해 만들어져 사람이 읽기 어려움
- 어셈블리어(assembly language) : 0과 1로 표현된 명령어(기계어)를 읽기 편한 형태로 번역한 언어
- 고급 언어로 작성된 소스 코드가 실행되려면 반드시 저급 언어인 명령어로 변환되어야 함
컴파일 언어&인터프리터 언어
컴파일 언어
- 컴파일러에 의해 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어
- 컴파일(compile) : 컴파일 언어로 작성된 소스 코드 → 저급 언어로 변환되는 과정
- 컴파일러(compiler) : 컴파일을 수행해 주는 도구
- 목적 코드(object code) : 컴파일러를 통해 저급 언어로 변환된 코드
인터프리터 언어
- 인터프리터에 의해 소스 코드가 한 줄씩 실행되는 고급 언어
- 소스 코드 전체가 저급 언어로 변환되는 컴파일 언어와 달리, 인터프리터 언어는 소스 코드를 한 줄씩 차례로 실행함
- 소스 코드 전체를 저급 언어로 변환하는 시간 기다릴 필요X
- N 번째 줄에 문법 오류 있어도 N-1번째 줄까지는 올바르게 수행됨
- 그러나 컴파일 언어보다 인터프리터 언어가 더 느림
- 인터프리터 언어는 한 줄씩 저급 언어로 해석해 실행해야 하기 때문
- 인터프리터(interpreter) : 소스 코드를 한 줄씩 적브 언어로 변환해 실행해 주는 도구
목적 파일 VS. 실행 파일
- 목적 파일 : 목적 코드로 이루어진 파일
- 실행 파일 : 실행 코드로 이루어진 파일
- 목적 파일(저급 언어) → ‘링킹’ → 실행 파일
2. 명령어의 구조
연산 코드와 오퍼랜드
- 명령어 : 연산 코드 + 오퍼랜드
- 연산 코드(Operation code) : 명령어가 수행할 연산 == 연산자
- 오퍼랜드(Operand) : 연산에 사용할 ‘데이터’ 또는 ‘데이터가 저장된 위치’ == 피연산자
붉은 글씨가 연산 코드, 검은 글씨가 오퍼랜드
오퍼랜드
- 보통 메모리 주소, 레지스터 이름이 담겨 있어 오퍼랜드 필드를 주소 필드라고도 함
- 오퍼랜드는 명령어 안에 하나도 없을 수도, 한 개만 있을 수도 그 이상 여러 개 있을 수도 있음
연산 코드
- 데이터 전송
- MOVE : 데이터를 옮겨라
- STORE : 메모리에 저장해라
- LOAD(FETCH) : 메모리에서 CPU로 데이터를 가져와라
- PUSH : 스택에 데이터를 저장해라
- POP : 스택의 최상단 데이터를 가져와라
- 산술/논리 연산
- ADD/SUBTRACT/MULTIPLY/DIVIDE : 덧셈/뺄셈/곱셈/나눗셈을 수행해라
- INCREMENT/DECREMENT : 오퍼랜드에 1을 더하라/1을 빼라
- ADD/OR/NOT : AND/OR/NOT 연산을 수행해라
- COMPARE : 두 개의 숫자 또는 TRUE/FALSE 값을 비교해라
- 제어 흐름 변경
- JUMP : 특정 주소로 실행 순서를 옮겨라
- CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
- HALT : 프로그램의 실행을 멈춰라
- CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
- RETURN : CALL을 호출할 때 저장했던 주소로 돌아가라
- 입출력 제어
- READ(INPUT) : 특정 입출력 장치로부터 데이터를 읽어라
- WRITE(OUTPUT) : 특정 입출력 장치로 데이터를 써라
- START IO : 입출력 장치를 시작하라
- TEST IO : 입출력 장치의 상태를 확인하라
주소 지정 방식
- 명령어 길이가 길어 명령어의 주소를 담는 경우가 많음(표현할 수 있는 정보 가짓수 커짐)
- 유효 주소(effective address) : 연산의 대상이 되는 데이터가 저장된 위치
- 주소 지정 방식(addressing mode) : 유효 주소를 찾는 방법
즉시 주소 지정 방식(immediate addressing mode)
- 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시
- 단점 : 표현할 수 있는 데이터 크기 작아짐
- 장점 : 연산에 사용할 데이터를 메모리/레지스터로부터 찾는 과정이 없어 빠름
직접 주소 지정 방식(direct addressing mode)
- 오퍼랜드 필드에 유효 주소를 직접적으로 명시
- 표현할 수 있는 오퍼랜드 필드 길이가 연산 코드의 길이만큼 짧아져 표현할 수 있는 유효 주소에 제한이 생길 수 있음
간접 주소 지정 방식(indirect addressing mode)
- 유효 주소의 주소를 오퍼랜드 필드에 명시
- 직접 주소 방식보다 표현할 수 있는 유효 주소 범위 넓어짐
- 2번 메모리 접근이 필요해 느림
레지스터 주소 지정 방식(register addressing mode)
- 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시
- 일반적으로 CPU 외부에 있는 메모리에 접근하는 것보다 CPU 내부에 있는 레지스터에 접근 하는 것이 빠름
⇒ 레지스터 주소 지정 방식은 빠르게 데이터 접근O
- 직접 주소 지정 방식과 같이 표현할 수 있는 레지스터 크기에 제한이 생길 수 있음
레지스터 간접 주소 지정 방식(register indirect addressing mode)
- 연산에 사용할 데이터를 메모리에 저장하고, 그 주소(유효 주소)를 저장한 레지스터를 오퍼랜드 필드에 명시
- 유효 주소를 찾는 과정이 간접 주소 지정 방식과 비슷하나, 메모리에 접근하는 횟수가 1번으로 줄어듦
주소 지정 방식에서 오퍼랜드 필드에 명시하는 값 정리
- 즉시 주소 지정 방식 : 연산에 사용할 데이터
- 직접 주소 지정 방식 : 유효 주소(메모리 주소)
- 간접 주소 지정 방식 : 유효 주소의 주소
- 레지스터 주소 지정 방식 : 유효 주소(레지스터 이름)
- 레지스터 간접 주소 지정 방식 : 유효 주소를 저장한 레지스터
스택&큐
스택(stack)
- 한쪽 끝이 막혀 있어 데이터를 차곡차곡 저장하고, 빼낼 때는 마지막으로 저잘한 데이터부터 빼냄
- LIFO(Last In First Out) : 나중에 저장한 데이터를 가장 먼저 빼내는 데이터 관리 방식(후입선출)
- PUSH : 스택에 새 데이터 저장하는 명령어
- POP : 스택에 저장된 데이터 꺼내는 명령어
큐(Queue)
- 한쪽으로 데이터를 저장하고, 다른 한쪽으로는 먼저 저장한 순서대로 데이터를 빼냄
- FIFO(First In First Out) : 가장 먼저 저장된 데이터부터 빼내는 데이터 관리 방식(선입선출)