본 글은 강민철 님의 혼자 공부하는 컴퓨터구조+운영체제를 읽고 정리한 내용입니다.
첨부된 이미지는 혼자 공부하는 컴퓨터구조+운영체제 유튜브 강의에서 캡쳐한 것입니다.
소스코드와 명령어
고급 언어
- 사람이 이해하고 작성하기 쉽게 만들어진 언어
- 알고 있는 대부분의 프로그래밍 언어가 고급 언어에 속함
- ex. C, Java, Python, ...
저급 언어
- 컴퓨터가 직접 이해하고 실행할 수 있는 언어
- 고급 언어로 작성된 소스 코드를 실행하려면 반드시 저급 언어로 변환해야 함!
- 저급 언어에는 두 가지 종류가 있음
- 기계어
- 어셈블리어
- 기계어: 0과 1의 명령어 비트로 이루어진 언어
- 즉, 0과 1로 이루어진 명령어 모음
- 오로지 컴퓨터만을 위해 만들어진 언어라 사람이 그 의미를 이해하기 어려움
- 어셈블리어: 0과 1로 표현된 명령어(기계어)를 읽기 편한 형태로 번역한 언어
- 기계어를 읽기 편하게 만든 저급 언어이므로, 어셈블리어를 이용해서 복잡한 프로그램을 만들기 어려움
- 그래서 고급 언어가 필요한 것..! (읽고 쓰기 편함 & 더 나은 가독성 & 편리한 문법)
컴파일 언어와 인터프리터 언어
- 고급 언어를 저급 언어로 변환하는 방식은 크게 두 가지 방식이 있음
- 컴파일 방식
- 인터프리트 방식
- 컴파일 언어: 컴파일 방식으로 작동하는 프로그래밍 언어
- 인터프리터 언어: 인터프리트 방식으로 작동하는 프로그래밍 언어
컴파일 언어
- 컴파일러에 의해 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어 (ex. C, C++)
- 컴파일: 컴파일 언어로 작성된 소스 코드 전체가 저급 언어로 변환되는 과정
- 컴파일러: 컴파일을 수행해주는 도구
- 소스 코드를 처음부터 끝까지 저급 언어로 컴파일하므로, 소스 코드 내에서 오류를 하나라도 발견하면 컴파일에 실패함
- 컴파일러를 통해 저급 언어로 변환된 코드를 목적 코드라고 함
인터프리터 언어
- 인터프리터에 의해 소스 코드가 한 줄씩 실행되는 고급 언어 (ex. Python)
- 인터프리터: 소스 코드를 한 줄씩 저급 언어로 변환하여 실행해주는 도구
- 컴퓨터와 대화하듯 소스 코드를 한 줄씩 실행하므로, 소스 코드 전체를 저급 언어로 변환하는 시간을 기다릴 필요가 없음
- 또한, 소스 코드 N번째 줄에 문법 오류가 있어도 N-1번째 줄까지는 잘 실행됨
- 일반적으로 인터프리터 언어는 컴파일 언어보다 느림
- ex) 영어 책을 한국어로 번역해서 한 번에 읽음 vs 영어 책을 한 줄씩 번역해서 읽어줌
- 전자는 번역된 책을 건네받기만 하면 되므로 더욱 빠른 것..!
목적 파일 vs 실행 파일
- 목적 파일: 목적 코드로 이루어진 파일
- 실행 파일: 실행 코드로 이루어진 파일
- 목적 코드가 실행 파일이 되려면 링킹이라는 작업을 거쳐야 함
- 링킹 작업까지 거쳐야 하나의 실행 파일이 만들어짐
- ex) main.o, helper.o (*.o는 목적 파일이라고 칭함)
- main.o에 없는 외부 기능(helper.o의 기능, 출력 기능 등)을 main.o와 연결 짓는 작업(=링킹)이 필요함
명령어의 구조
연산 코드와 오퍼랜드
- 명령어는 연산 코드와 오퍼랜드로 구성되어 있음
- 연산 코드(연산자): 명령어가 수행할 연산
- 오퍼랜드(피연산자): 연산에 사용할 데이터 or 연산에 사용할 데이터가 저장된 위치
- 즉, "무엇을 대상으로, 어떤 작동을 수행해라"라는 구조로 되어 있음
- 기계어와 어셈블리어 또한 명령어이므로, 연산 코드와 오퍼랜드로 구성되어 있음
- ex) push rbp, mov rbp, rsp, ...
오퍼랜드
- "연산에 사용할 데이터" or "연산에 사용할 데이터가 저장된 위치"를 의미함
- 따라서 오퍼랜드 필드에는 데이터나 레지스터 주소가 올 수 있음
- 대부분 데이터를 직접 명시하기보다 메모리 주소나 레지스터 이름을 담음
- 그래서 주소 필드라고도 부름
- 오퍼랜드는 명령어 안에 없을 수도, 1개, 2개, 3개, ... 등 여러 개가 있을 수 있음
- 0-주소 명령어: 오퍼랜드가 하나도 없는 명령어
- 1-주소 명령어: 오퍼랜드가 하나인 명령어
- 2-주소 명령어: 오퍼랜드가 두 개인 명령어
- 3-주소 명령어: 오퍼랜드가 세 개인 명령어
연산코드
- "명령어가 수행할 연산"을 의미함
- 가장 기본적인 연산 코드 유형은 크게 네 가지로 나눌 수 있음
- 데이터 전송
- 산술/논리 연산
- 제어 흐름 변경
- 입출력 제어
- 데이터 전송
- MOVE: 데이터 옮겨라
- STORE: 메모리에 저장해라
- LOAD(FETCH): 메모리에서 CPU로 데이터 가져와라
- PUSH: 스택에 데이터 저장해라
- POP: 스택의 최상단 데이터 가져와라
- 산술/논리 연산
- ADD / SUBSTRACT / MULTIPLY / DIVIDE: 덧셈 / 뺄셈 / 곱셈 / 나눗셈 수행해라
- INCREMENT / DECREMENT: 오퍼랜드에 1 더해라 / 1 빼라
- AND / OR / NOT: AND / OR / NOT 연산 수행해라
- COMPARE: 두 개의 숫자 또는 TRUE / FALSE 값 비교해라
- 제어 흐름 변경
- JUMP: 특정 주소로 실행 순서 옮겨라
- CONDITIONAL JUMP: 조건에 부합할 때 특정 주소로 실행 순서 옮겨라
- HALT: 프로그램의 실행 멈춰라
- CALL: 되돌아올 주소를 저장한 채, 특정 주소로 실행 순서 옮겨라
- RETURN: CALL을 호출했던 주소로 돌아가라
- 입출력 제어
- READ (INPUT): 특정 입출력 장치로부터 데이터 읽어라
- WRITE (OUTPUT): 특정 입출력 장치로부터 데이터 써라
- START IO: 입출력 장치를 시작해라
- TEST IO: 입출력 장치의 상태 확인해라
주소 지정 방식
- 명령어 길이 때문에 오퍼랜드 필드에 메모리나 레지스터의 주소를 담음
- ex) 명령어의 크기가 16비트, 연산 코드 필드가 4비트인 2-주소 명령어
- 오퍼랜드 필드당 6비트 정도 사용 가능함
- 하나의 오퍼랜드 필드로 표현 가능한 데이터 개수는 2^6개(=64개)
- 데이터가 아닌 메모리 주소를 담는다면?
- 표현할 수 있는 데이터의 크기가 하나의 메모리 주소에 저장할 수 있는 공간만큼 커짐!
- 주소 지정 방식: 연산에 사용할 데이터 위치를 찾는 방법
- 즉, 연산의 대상이 되는 데이터가 저장된 위치(=유효 주소)를 찾는 방법
즉시 주소 지정 방식
- 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시하는 방법
- 장점
- 연산에 사용할 데이터를 메모리나 레지스터로부터 찾는 과정이 없어, 다른 방식보다 빠름
- 단점
- 표현할 수 있는 데이터의 크기가 작아짐
직접 주소 지정 방식
- 오퍼랜드 필드에 유효 주소를 직접적으로 명시하는 방법
- 장점
- 즉시 주소 지정 방식보다 표현할 수 있는 데이터의 크기가 늘어남
- 단점
- 표현할 수 있는 오퍼랜드 필드의 길이가 연산 코드의 길이만큼 짧아져 표현할 수 있는 유효 주소에 제한이 있음
간접 주소 지정 방식
- 유효 주소의 주소를 오퍼랜드 필드에 명시함
- 장점
- 직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 더 넓어짐
- 명령어의 주소 필드보다 더 큰 크기의 유효 주소를 메모리에 저장할 수 있기 때문..!
- 단점
- 두 번의 메모리 접근이 필요하므로 비교적 느림
레지스터 주소 지정 방식
- 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시하는 방법
- 장점
- 직접 주소 지정 방식보다 빠름
- CPU 외부에 있는 메모리에 접근하는 것보다 내부에 있는 레지스터에 접근하는 것이 더욱 빠르기 때문
- 단점
- 직접 주소 지정 방식과 마찬가지로, 표현할 수 있는 레지스터 크기에 제한이 생길 수 있음
레지스터 간접 주소 지정 방식
- 연산에 사용할 데이터를 메모리에 저장하고, 그 유효 주소를 저장한 레지스터를 오퍼랜드 필드에 명시하는 방법
- 장점
- 간접 주소 지정 방식과 달리 메모리에 접근하는 횟수가 한 번으로 줄어들어 더욱 빠름
'CS > 컴퓨터구조' 카테고리의 다른 글
[혼공컴운] Ch 04. CPU의 작동 원리 (0) | 2024.12.30 |
---|---|
[혼공컴운] Ch 02. 데이터 (0) | 2024.12.21 |
[혼공컴운] Ch 01. 컴퓨터 구조 시작하기 (1) | 2024.12.20 |