Priv's Blog

3. 명령어 본문

Dev. Study Note/Computer Architecture

3. 명령어

Priv 2023. 3. 12. 21:25


 

 

1. 소스 코드, 명령어

컴퓨터는 명령어를 읽어 동작한다.

우리는 C++, C#과 같은 프로그래밍 언어를 사용해 컴퓨터에게 내릴 명령들을 작성한다.

우리가 작성한 명령들은 '소스 코드'라고 부르며, 컴퓨터는 이 소스 코드를 컴파일러를 통해 명령어(기계어)로 변환하여 명령을 수행한다.

 

1.1) 고급 언어, 저급 언어

  • 고급 언어: 사람이 이해하기 쉽게 작성된 프로그래밍 언어를 칭한다.
  • 저급 언어: 컴퓨터가 이해하기 쉽게 작성된 프로그래밍 언어를 칭한다.

저급 언어보다 가독성이 높고 다루기가 쉽지만 저급 언어보다 상대적으로 속도가 느리다.

일반적으로 저급 언어는 기계어, 어셈블리어까지를 일컫는다. (C언어는 고급 언어에 해당)

저급 언어는 실행 속도가 고급 언어보다 상대적으로 빠르지만, 가독성이 낮고 다루기가 불편해 배우기가 어려우며 유지보수 또한 상당히 힘들다.

이 때문에 대부분 고급 언어를 사용하며, 저급 언어는 하드웨어와 밀접한 연관이 있는 특수 분야에서만 제한적으로 사용된다.

 

1.2) 컴파일 언어, 인터프리터 언어

고급 언어로 작성된 소스 코드들은 컴파일 또는 인터프리터를 통해 저급 언어로 변환된다.

컴파일을 사용하는 언어는 컴파일 언어, 인터프리터를 사용하는 언어는 인터프리터 언어라고 칭한다.

  • 컴파일 언어: 컴파일러에 의해 소스 코드 전체가 한 번에 변환되어 실행되는 구조의 고급 언어이다. C언어가 대표적이다.
  • 인터프리터 언어: 인터프리터에 의해 소스 코드가 한 줄씩 변환되어 실행되는 구조의 고급 언어이다. Python이 대표적이다.

인터프리터 언어가 상대적으로 컴파일 언어보다 속도가 느리다.

현대에는 Java처럼 컴파일과 인터프리터를 동시에 사용하는 방식의 언어들도 존재한다.

 

1.3) 목적 파일, 실행 파일

고급 언어로 작성된 소스 코드가 컴파일러를 통해 컴파일되면 저급 언어에 해당하는 목적 코드로 변환된다.

이렇게 만들어진 목적 코드가 실행되기 위해서는 링킹(linking)이라는 작업을 거쳐야 한다.

C언어를 통해 helper.c, main.c라는 소스 코드를 저장했다고 가정해 보자.

helper.c 안에는 'HELPER_더하기'라는 함수가 구현되어 있다.

main.c 안에는 'HELPER_더하기' 기능과 함께 '화면_출력'이라는 기능을 가져다 사용한다.

이 두 파일을 컴파일 한 뒤, 생성된 파일을 helper.o, main.o라고 가정한다.

컴파일을 통해 생성된 이 두 파일은 그대로 실행할 수 없다.

main.o에는 helper.o에 있는 'HELPER_더하기' 기능에 대한 정보가 담겨있지 않기 때문이다.

즉, helper.o에 있는 'HELPER_더하기' 기능과 main.o에 있는 '화면_출력' 이 서로 연결되어야 한다.

이 작업을 링킹이라고 부른다.

 


 

2. 명령어 구조

2.1) 연산 코드, 오퍼랜드

명령어는 연산 코드, 오퍼랜드로 구성되어 있다.

  • 연산 코드: 명령어가 수행할 연산. (연산자)
  • 오퍼랜드: 연산에 사용할 데이터 또는 연산에 사용할 데이터가 저장된 위치. (피연산자)

오퍼랜드에는 숫자, 문자 등을 나타내는 데이터, 메모리나 레지스터 주소 등이 올 수 있다.

일반적으로 연산에 사용할 직접적인 데이터가 오지 않고, 메모리 주소 또는 레지스터의 주소가 오는 것이 일반적이다.

오퍼랜드가 하나도 없으면 '0-주소 명령어', 1개 있으면 '1-주소 명령어', n개 있으면 'n-주소 명령어'라고 부른다.

연산 코드는 데이터 전송, 산술/논리 연산, 제어 흐름 변경, 입출력 제어로 유형이 나눠진다.

이 연산 코드는 CPU의 종류에 따라 달라지기 때문에 하드웨어의 성능을 확인한 후에 사용해야 한다.

 

2.2) 주소 지정 방식

명령어 하나가 n비트로 구성되어 있으며, 연산 코드 필드가 m비트를 차지한다고 가정해 보자.

여기서 1-주소 명령어라고 한다면 오퍼랜드 필드가 차지하는 비트는 n-m비트이다.

즉, 오퍼랜드가 많을수록 하나의 오퍼랜드가 차지할 수 있는 크기는 점점 줄어든다.

이를 해결하기 위해 오퍼랜드 필드에 메모리의 주소를 담는 것이다.

연산에 쓸 실질적인 데이터는 용량이 상대적으로 더 큰 메모리에 담아두고, 그 메모리의 주소만 오퍼랜드 필드에 명시한다면 표현할 수 있는 정보의 가짓수가 확장된다.

여기서 연산 코드에 쓸 데이터가 저장된 위치는 유효 주소(Effective address)라고 부른다.

 

- 즉시 주소 지정 방식

연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시한다.

표현 가능한 데이터 크기는 작아지지만 상대적으로 속도가 빠르다.

 

- 직접 주소 지정 방식

오퍼랜드 필드에 유효 주소를 직접 명시한다.

오퍼랜드 필드의 길이가 연산 코드의 길이만큼 짧아진다.

 

- 간접 주소 지정 방식

오퍼랜드 필드에 유효 주소의 주소를 명시한다.

직접 주소 지정 방식보다 명시할 수 있는 유효 주소의 범위는 더 넓지만, 메모리 참조를 2번 이상 해야 하므로 속도가 느리다.

 

- 레지스터 주소 지정 방식

데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시한다.

레지스터는 CPU 내부에 있는 저장소로 속도가 상당히 빠른 편이다.

이 덕분에 빠르게 데이터를 불러올 수 있으나, 레지스터 크기에 따라 제한이 생길 수 있다.

 

- 레지스터 간접 주소 방식

연산에 사용할 데이터는 메모리에 저장하고, 유효 주소를 레지스터에 저장한다.

오퍼랜드 필드에는 유효 주소를 저장한 레지스터의 주소가 담긴다.

메모리에 접근하는 횟수가 1번이기 때문에 간접 주소 저장 방식보다 좀 더 빠르다.

 


 


수고하셨습니다!


'Dev. Study Note > Computer Architecture' 카테고리의 다른 글

6. 보조기억장치  (0) 2023.03.28
5. RAM  (0) 2023.03.26
4. CPU  (0) 2023.03.19
2. 데이터  (0) 2023.03.12
1. 컴퓨터 구조  (0) 2023.03.11
Comments