03-1. 소스 코드와 명령어
(1) 고급 언어와 저급 언어
고급 언어: 사람을 위한 언어로, 대부분의 프로그래밍 언어가 고급 언어에 속한다.
저급 언어: 컴퓨터가 직접 이해하고 실행할 수 있는 언어
고급 언어로 작성된 소스 코드가 실행되려면 반드시 저급 언어, 즉 명령어로 변환되어야 한다.
저급 언어에는 기계어와 어셈블리어 두 가지 종류가 있다.
기계어(machine code): 0과 1로 이루어진 명령어로 구성된 저급 언어
기계어는 오로지 컴퓨터만을 위해 만들어진 언어이기 때문에 사람이 읽으면 그 의미를 이해하기 어렵다.
어셈블리어(assembly language): 0과 1로 이루어진 기계어를 읽기 편한 형태로 번역한 저급 언어
어셈블리어를 통해 컴퓨터가 프로그램을 어떤 과정으로 실행하는지, 즉 프로그램이 어떤 절차로 작동하는지를 가장 근본적인 단계에서부터 하나하나 추적하고 관찰할 수 있다.
(2) 컴파일 언어와 인터프리터 언어
개발자들이 고급 언어로 작성한 소스 코드가 저급 언어로 변환되는 방식은 크게 컴파일 방식과 인터프리트 방식이 있다.
컴파일 언어: 컴파일러에 의해 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어
Ex) C언어
컴파일(compile): 컴파일 언어로 작성된 소스 코드 전체가 저급 언어로 변환되는 과정
컴파일러(compiler) :컴파일을 수행해 주는 도구
컴파일러가 소스 코드 내에서 오류를 하나라도 발견하면 해당 소스 코드는 컴파일에 실패한다.
목적 코드(object code): 컴파일러를 통해 저급 언어로 변환된 코드
인터프리터 언어: 인터프리터에 의해 소스 코드가 한 줄씩 실행되는 고급 언어
Ex) Python
소스 코드 전체가 저급 언어로 변환되는 컴파일 언어와 달리, 인터프리터 언어는 소스 코드를 한 줄씩 차례로 실행한다.
인터프리터(interpreter): 소스 코드를 한 줄씩 저급 언어로 변환하여 실행해 주는 도구
소스 코드를 한 줄씩 실행하기 때문에 소스 코드 N번째 줄에 문법 오류가 있더라도 N-1 번재 줄까지는 올바르게 수행된다.
※ 하나의 언어가 반드시 컴파일 방식과 인터프리트 방식 중 하나의 방식으로만 작동하는 것은 아니며, 현대의 많은 프로그래밍 언어 중에서는 컴파일 언어와 인터프리터 언어 간의 경계가 모호한 경우가 많다.
※ 목적 코드가 실행 파일이 되기 위해서는 링킹(목적 파일에 없는 외부 기능을 연결짓는 것)이라는 작업을 거쳐야 한다.
03-2. 명령어의 구조
(1) 연산 코드와 오퍼랜드
명령어는 연산 코드와 오퍼랜드로 구성되어 있다.
연산 코드(operation code): '명령어가 수행할 연산'으로, '연산자'라고도 부른다.
오퍼랜드(operand): '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'로, '피연산자'라고도 부른다.
오퍼랜드 필드에는 숫자와 문자 등을 나타내는 데이터 또는 메모리나 레지스터 주소가 올 수 있다.
다만 연산에 사용할 데이터를 직접 명시하기보다는 많은 경우 데이터가 저장된 위치를 명시하기 때문에 주소 필드라고 부르기도 한다.
0-주소 명령어: 오퍼랜드가 하나도 없는 명령어
1-주소 명령어: 오퍼랜드가 하나인 명령어
2-주소 명령어: 오퍼랜드가 두 개인 명령어
3-주소 명령어: 오퍼랜드가 세 개인 명령어
연산 코드는 기본적으로 네 가지 유형으로 나눌 수 있다.
1. 데이터 전송
- MOVE: 데이터를 옮겨라
- STORE: 데이터를 저장하라
- LOAD(FETCH): 메모리에서 CPU로 데이터를 가져와라
- PUSH: 스택에 데이터를 저장하라
- POP: 스택의 최상단 데이터를 가져와라
2. 산술/논리 연산
- ADD / SUBSTRACT / MULTIPLY / DIVIDE: 덧셈 / 뺄셈 / 곱셈 / 나눗셈을 수행하라
- INCREMENT / DECREMENT: 오퍼랜드에 1을 더하라 / 오퍼랜드에 1을 빼라
- AND / OR / NOT: AND / OR / NOT 연산을 수행하라
- COMPARE: 두 개의 숫자 또는 TRUE / FALSE 값을 비교하라
3. 제어 흐름 변경
- JUMP: 특정 주소로 실행 순서를 옮겨라
- CONDITIONAL JUMP: 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
- HALT: 프로그램의 실행을 멈춰라
- CALL: 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
- RETURN: CALL을 호출할 때 저장했던 주소로 돌아가라
4. 입출력 제어
- READ(INPUT): 특정 입출력 장치로부터 데이터를 읽어라- WRITE(OUTPUT): 특정 입출력 장치로 데이터를 써라- START IO: 입출력 장치를 시작하라- TEST IO: 입출력 장치의 상태를 확인하라
(2) 주소 지정 방식
오퍼랜드 필드에 데이터가 아닌 메모리 주소가 담긴다면 표현할 수 있는 데이터의 크기는 하나의 메모리 주소에 저장할 수 있는 공간만큼 커지고, 레지스터 이름을 명시할 때도 해당 레지스터가 저장할 수 있는 공간만큼 커진다.
때문에 오퍼랜드 필드에 메모리나 레지스터의 주소를 담는 경우가 많다.
유효 주소(effective address): 연산의 대상이 되는 데이터가 저장된 위치
주소 지정 방식(addressing mode): 연산에 사용할 데이터 위치를 찾는 방법. 즉, 유효 주소를 찾는 방법
즉시 주소 지정 방식
: 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시하는 방식
표현할 수 있는 데이터의 크기가 작아지는 단점이 있지만, 연산에 사용할 데이터를 메모리나 레지스터로부터 찾는 과정이 없기 때문에 다른 주소 지정 방식들보다 빠르다.
직접 주소 지정 방식
: 오퍼랜드 필드에 유효 주소를 직접적으로 명시하는 방식
표현할 수 있는 데이터의 크기는 즉시 주소 지정 방식보다 더 커졌지만, 여전히 유;효 주소를 표현할 수 있는 범위가 연산 코드의 비트 수만큼 줄어들었다.
간접 주소 지정 방식
: 유효 주소의 주소를 오퍼랜드 필드에 명시하는 방식
직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 더 넓어졌으나, 두 번의 메모리 접근이 필요하기 때문에 일반적으로 느린 방식이다.
레지스터 주소 지정 방식
: 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시하는 방식
일반적으로 CPU 외부에 있는 메모리에 접근하는 것보다 CPU 내부에 있는 레지스터에 접근하는 것이 더 빠르기 때문에, 직접 주소 지정 방식보다 빠르게 데이터에 접근할 수 있다.
하지만 직접 주소 지정 방식과 마찬가지로 표현할 수 있는 레지스터 크기에 제한이 생길 수 있다.
레지스터 간접 주소 지정 방식
: 연산에 사용할 데이터를 메모리에 저장하고, 그 주소를 저장한 레지스터를 오퍼랜드 필드에 명시하는 방식
유효 주소를 찾는 과정이 간접 주소 지정 방식과 비슷하지만, 메모리에 접근하는 횟수가 한 번으로 줄어든다는 장점이 있다.
메모리에 접근하는 것이 레지스터에 접근하는 것보다 느리기 때문에 레지스터 간접 주소 방식은 간접 주소 지정 방식보다 빠르다.
'Computer Science > Computer Architecture' 카테고리의 다른 글
[ 혼자 공부하는 컴퓨터구조 + 운영체제 ] Chapter08. 입출력장치 (1) | 2024.06.06 |
---|---|
[ 혼자 공부하는 컴퓨터구조 + 운영체제 ] Chapter06. 메모리와 캐시 메모리 (0) | 2024.06.02 |
[ 혼자 공부하는 컴퓨터구조 + 운영체제 ] Chapter04. CPU의 작동 원리 (0) | 2024.05.25 |
[ 혼자 공부하는 컴퓨터구조 + 운영체제 ] Chapter02. 데이터 (0) | 2024.04.26 |
[ 혼자 공부하는 컴퓨터구조 + 운영체제 ] Chapter 01. 컴퓨터 구조 시작하기 (0) | 2024.04.19 |