명령어
명령어(Operand)는 컴퓨터를 실질적으로 움직이게하는 정보를 말합니다. 또는 데이터를 이용하여 CPU 를 작동시키는 정보를 말합니다.
명령어의 구조
명령어는 명령어가 수행할 연산을 담고 있는 op-code(연산코드), 연산에 사용될 데이터 혹은 레지스터 혹은 연산에 사용될 데이터가 저장된 위치 를 나타내는 operand(주소필드) 로 구성된다.

Note
연산에 사용될 데이터 자체보다 연산에 필요한 데이터가 저장된 위치(주소)가 훨씬 더 많이 저장됩니다. 그래서 operand 필드를 “주소필드” 라고 부르기도 합니다.
다양한 명령어의 구조
기본적으로 명령어는 opcode(연산코드)와 operand(주소필드)로 구성됩니다. 하지만 명령어를 이루는 operand(주소필드)는 없을 수도 있고 여러개가 있을 수도 있습니다. 명령어의 종류는 다음과 같이 있습니다.
0-주소 명령어: 주소필드가 없는 명령어이며opcode구조를 갖고 있습니다.1-주소 명령어: 하나의 주소필드가 있는 명령어이며opcode operand(주소필드)구조를 갖고 있습니다.2-주소 명령어: 두개의 주소필드가 있는 명령어이며opcode operand(주소필드) operand(주소필드)구조를 갖고 있습니다.3-주소 명령어: 세개의 주소필드가 있는 명령어이며opcode operand(주소필드) operand(주소필드) operand(주소필드)구조를 갖고 있습니다.

연산코드
CPU 가 수행할 연산에 대한 정보를 담고있는 opcode(연산코드) 는 CPU 마다 종류가 다르고 개수도 다릅니다. 하지만 공통으로 갖고있는 연산코드도 있습니다.
- 데이터 전송
- MOVE : 데이터를 옮기는 연산 (ex. 레지스터에서 다른 레지스터로 데이터를 옮깁니다.)
- STORE : 메모리에 저장해라 (ex. 메모리에 어떤 값을, 혹은 어떤 메모리 위치에 저장되어있는 값을 저장합니다.)
- LOAD(FETCH) : 메모리에서 CPU 로 데이터를 가져옵니다.
- PUSH : Stack 에 데이터를 저장합니다.
- POP : Stack 의 최상단 데이터를 가져옵니다.
- 산술/논리 연산
- ADD / SUBSTRACT / MULTIPLY / DIVIDE : 덧셈 / 뺼셈 / 곱셈 / 나눗셈 을 수행합니다.
- INCREMENT / DECREMENT : Operand 에 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 : 입출력 장치의 상태를 확인합니다.
명령어 주소 지정 방식
앞서 명령어는 Opcode & Operand 로 구성되어있고 Operand 에는 값 자체나, 값이 들어있는 메모리주소가 저장될 수 있다고 언급했습니다. 그리고 많은 경우에 Operand 필드에는 값 자체보단 값이 들어있는 메모리 주소가 들어있을 확률이 높다 고도 언급했습니다. 그렇다면 왜 Operand 에는 값자체보단, 값이 들어있는 메모리주소가 저장되어 있는 경우가 더 많을까요?
주소필드에 값의 주소를 저장하는 이유
Operand 에 데이터 자체보다 연산에 필요한 데이터의 주소값을 명시하는 이유는 명령어내에서 표현할 수 있는 정보의 크기를 제한받지 않도록 하기 위함입니다.
예를 들어 명령어의 크기가 1WORD(16Bit) & 명령어의 종류는 2-주소지정 명령어 & 명령어의 opcode 는 4bit, 각 operand(주소필드) 는 6bit 씩 갖고 있다고 가정해보면 다음과 같이 그려볼 수 있습니다.

명령어 내부 하나의 Operand(주소필드)가 표현할 수 있는 정보(데이터) 크기는 2 ^ 6 = 64개입니다. 이는 매우 작은 값입니다.

만약 해당 명령어가 3-주소지정 명령어 를 사용한다고 치면, 하나의 Operand 당 표현할 수 있는 정보(데이터) 크기는 2의 4승인 8개 로 2-주소지정 명령어를 사용할때보다 표현 범위가 더 줄어들게 됩니다.

이와 달리 Operand 에 데이터의 값이 아닌, 데이터가 저장된 주소(메모리 주소)를 명시하면 정보를 표현할 수 있는 크기가 매우 커지게 됩니다.
아래 2-주소 명령어 구조에서, 하나의 Operand는 2 ^ 6 = 64개의 정보를 표현할 수 있습니다. 그러나 Operand 필드에 60000이라는 값을 직접 저장할 수는 없습니다. 왜냐하면 60000은 6비트로 표현할 수 있는 범위(0~63)를 초과하기 때문입니다. 그렇다면 60000이라는 값이 저장된 메모리 주소를 Operand에 저장하면 어떻게 될까요?
아래 그림에서 오른쪽을 보면, 주소당 16비트씩 데이터를 저장할 수 있는 메모리가 있고, 10번지 주소에는 60000이라는 데이터가 저장되어 있습니다. 이제 명령어의 Operand 필드에는 값 자체가 아닌, 값이 저장된 메모리 주소(10번지)를 저장하게 됩니다. 그러면 명령어는 해당 주소를 통해 실제 데이터를 가져올 수 있습니다.
즉, Operand에 값 대신 주소를 저장하면, 표현할 수 있는 정보의 크기가 2 ^ 16 = 65536개로 늘어나게 되어 훨씬 더 다양한 데이터를 다룰 수 있게 됩니다. 이러한 이유로 대부분의 명령어에서 Operand에는 값 그 자체(Value)보다, 값이 저장된 위치(Address)를 저장하는 방식이 사용됩니다.
여기서 연산에 사용될 데이터가 저장된 주소를 Effective Address(유효주소) 라고 합니다.

유효주소
Effective Address는 연산에 사용할 실제 데이터가 저장된 위치를 말합니다.
- 예를 들어,
LOAD 10이라는 명령어에서 유효 주소는10번지입니다. - 만약
LOAD R1과 같이 레지스터가 사용되었다면, 유효 주소는R1이 됩니다.

명령어 주소 지정 방식
명령어 주소 지정 방식은 연산에 필요한 데이터가 어디에 저장되어 있는지를 지정하는 방법을 말합니다.
- 다양한 주소 지정 방식에 따라 데이터의 위치를 해석하거나 계산합니다.
- 이 과정에서 필요한 주소를 계산하여
유효 주소(Effective Address)를 결정하게 됩니다.
쉽게 말해, 명령어 주소 지정 방식은 “명령어가 사용할 데이터가 어디에 있는지를 알려주는 규칙”이라고 이해하면 됩니다.
직접 주소 지정 방식
- Direct Addressing Mode 라고 불립니다.
- Operand 필드에
유효주소(Effective Address)를 직접 명시하는 방법입니다. - 유효주소(Effective Address) 를 표현할 수 있는 크기가 연산 코드의 비트 수만큼 줄어드는 단점이 있습니다.

간접 주소 지정 방식
- Indirect Addressing Mode 라고 불립니다.
- 직접 주소 지정 방식의 단점 (유효주소를 표현할 수 있는 크기가 연산 코드의 비트 수만큼 줄어드는 것)을 보완하기 위해 고안된 방법입니다.
- Operand 필드에
유효주소(Effective Address)의 주소를 명시하는 방법입니다. - 메모리를 여러번 찾아야하기 때문에 당연히 직접 주소지정 방식보다 느리다는 단점이 있습니다.
Note
CPU 가 메모리에서 값을 찾는 것은 느리기 때문에 메모리 접근을 빈도수를 최소화하는것이 속도면에서 훨씬 좋습니다.

레지스터 주소 지정 방식
- Register Addressing Mode 라고 불립니다.
- 연산에 사용할 데이터가 저장된
레지스터를 명시하는 방법입니다.
메모리에 접근하는 속도보다 레지스터에 접근하는 것이 더 빠르다.
Memory 는 CPU 외부에 위치합니다. 이와 달리 레지스터는 CPU 의 구성요소이기 때문에 CPU 내부에 위치합니다. 따라서 Memory 에 접근하는 속도보다 Register 에 접근하는 것이 더 빠릅니다.

레지스터 간접 주소 지정 방식
- Register Indirect Addressing Mode 라고 불립니다.
- 연산에 사용할
데이터를 메모리에 저장해두고, 그 주소를 저장한 레지스터를 Operand 에 명시하는 방법입니다.
