본문 바로가기
시리즈/컴퓨터 구조

[컴퓨터 구조] 명령어에 대해 알아보기

by 되고싶은노력가 2025. 1. 24.

소스코드와 명령어

컴퓨터는 C, C++, Java, Pyhon과 같은 프로그래밍 언어를 이해하지 못하기 때문에 컴퓨터 내부 명령어로 변환해주어야 합니다.

 

위에 언급한 언어처럼 사람이 쉽게 이해할 수 있도록 만들어진 언어를 고급 언어라고 합니다. 반대로 컴퓨터가 직접 이해하고 실행할 수 있는 언어를 저급 언어라고 합니다.

 

저급 언어에는 두 가지 종류가 있습니다. 바로 기계어어셈블리어입니다.

 

기계어

기계어란 0과 1의 명령어 비트로 이루어진 언어로 이진수로 표현되지만 이를 나열하면 너무 길어지기에 십육진수로 표현하기도 합니다.


어셈블리어

어셈블리어는 0과 1로 이루어진 기계어를 읽기 편한 형태로 번역한 저급 언어입니다.

어셈블리어 예시


앞서 고급 언어로 작성된 소스 코드는 결국 저급 언어로 변환되어 실행된다고 했습니다. 그렇다면 어떻게 변환을 하는지 알아보겠습니다.

 

방식은 크게 컴파일 방식과 인터프리트 방식이 있습니다. 컴파일 방식으로 작동하는 프로그래밍 언어를 컴파일 언어, 인터프리트 방식으로 작동하는 프로그래밍 언어를 인터프리터 언어라고 합니다.

 

컴파일 언어

컴파일 언어는 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어입니다. 대표적으로는 C언어로, 컴파일 언어작성된 소스 코드 전체를 저급 언어로 변환해주는 과정컴파일, 그리고 컴파일을 수행해 주는 도구컴파일러라고 합니다. 소스 코드에 문법적인 오류는 없는지, 불필요한 코드가 없는지 등을 따지며 변환하는데 소스 코드를 처음부터 끝까지 저급 언어로 컴파일하기에 오류가 하나라도 발생하면 컴파일에 실패합니다.


인터프리터 언어

인터프리터 언어는 인터프리터에 의해 소스 코드가 한 줄씩 실행되는 고급 언어입니다. 대표적으로는 Python으로, 컴파일 언어와 다르게 한 줄씩 변환되기 때문에 소스 코드 전체를 저급 언어로 변환하는 시간을 기다릴 필요가 없습니다. 그렇기 때문에 인터프리터 언어가 컴파일 언어보다 빠르다고 생각할 수 있지만 일반적으로 인터프리터 언어는 컴파일 언어보다 느립니다.

* C,C++ 처럼 컴파일인지 인터프리터인지 명확히 구분되는 언어도 있으나 경계가 모호한 경우가 많습니다. Python 또한 컴파일을 하지 않는 것은 아니며 Java의 경우 저급 언어가 되는 과정에서 컴파일과 인터프리트를 동시에 수행합니다.

 

 


 

명령어의 구조

명령어가 컴퓨터 내부에서 어떻게 동작하는지 봤다면 명령어의 구조와 자세한 작동 원리에 대해 알아보겠습니다.

 

명령어는 연산 코드, 오퍼랜드, 주소 지정 방식이라는 개념이 존재합니다.

 

연산 코드와 오퍼랜드

 

명령어연산 코드오퍼랜드로 구성되어 있습니다. 색 배경 필드 값, 즉 '명령어가 수행할 연산'을 연산 코드라 하고 흰색 배경 필드 값, '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'를 오퍼랜드라고 합니다. 연산코드는 연산자, 오퍼랜드는 피연산자라고도 부릅니다.

 

연산 코드

연산 코드 종류는 매우 많지만, 기본적인 연산 코드 유형은 크게 네 가지로 나눌 수 있습니다.

  1. 데이터 전송
  2. 산술/논리 연산
  3. 제어 흐름 변경
  4. 입출력 제어

데이터 전송

  • MOVE : 데이터를 옮겨라
  • STORE : 메모리에 저장하라
  • LOAD (FETCH) : 메모리에서 CPU로 데이터를 가져와라
  • PUSH : 스택에 데이터를 저장하라
  • POP : 스택의 최상단 데이터를 가져와라

산술/논리 연산

  • ADD / SUBTRACT / MULTIPLY / DIVIDE : 덧셈 / 뺄셈 / 곱셈 / 나눗셈을 수행하라
  • INCREMENT / DECREMENT : 오퍼랜드에 1을 더하라 / 오퍼랜드에 1을 빼라
  • AND / OR / NOT : AND / OR / NOT 연산을 수행하라
  • COMPARE : 두 개의 숫자 또는 TRUE / FALSE 값을 비교하라

제어 흐름 변경

  • JUMP : 특정 주소로 실행 순서를 옮겨라
  • CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
  • HALT : 프로그램의 실행을 멈춰라
  • CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
  • RETURN : CALL을 호출할 때 저장했던 주소로 돌아가라

입출력 제어

  • READ (INPUT) : 특정 입출력 장치로부터 데이터를 읽어라
  • WIRTE (OUTPUT) : 특정 입출력 장치로 데이터를 써라
  • START IO : 입출력 장치를 시작하라
  • TEST IO : 입출력 장치의 상태를 확인하라

오퍼랜드

오퍼랜드 필드에는 숫자와 문자 등을 나타내는 데이터 또는 메모리나 레지스터 주소가 올 수 있습니다. 보통 직접 명시하기보다는 메모리 주소나 레지스터 이름이 담깁니다. 그래서 주소 필드라고 부르기도 합니다.

 

위에 나온 그림처럼 오퍼랜드 명령어 안에는 하나도 없을 수도 있고, 한 개, 두 개 또는 세 개 등 여러 개가 있을 수도 있습니다.


주소 지정 방식

오퍼랜드에 바로 데이터를 담지 않는 이유는 정보의 가짓수가 작기 때문입니다. 더욱이 연산 코드의 공간이 커지거나 2-주소 명령어, 3-주소 명령어에서는 더 작아집니다.

 

그렇기 때문에 연산에 사용할 데이터 위치를 찾는 방법 즉, 주소 지정 방식이 사용되었습니다. 현대 CPU는 다양한 주소 지정 방식을 사용하는데 대표적으로는 즉시 주소 지정 방식, 직접 주소 지정 방식, 간접 주소 지정 방식, 레지스터 주소 지정 방식, 레지스터 간접 주소 지정 방식 등 다섯 가지가 있습니다.

 

즉시 주소 지정 방식

즉시 주소 지정 방식연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시하는 방식입니다. 데이터의 크기는 작지만 메모리나 레지스터로부터 찾는 과정이 없기 때문에 다른 주소 지정 방식들보다 빠릅니다.

 


직접 주소 지정 방식

직접 주소 지정 방식오퍼랜드 필드에 유효 주소를 직접적으로 명시하는 방식입니다. 표현할 수 있는 데이터의 크기는 즉시 주소 지정 방식보다 더 커졌지만, 여전히 유효 주소를 표현할 수 있는 범위가 연산 코드의 비트 수만큼 줄어들었습니다.


간접 주소 지정 방식

간접 주소 지정 방식은 유효 주소의 주소를 오퍼랜드 필드에 명시합니다. 직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 넓어졌으나 메모리에 두 번 접근하기에 앞서 설명한 주소 지정 방식들보다 일반적으로 느립니다.


레지스터 주소 지정 방식

레지스터 주소 지정 방식은 직접 주소 지정 방식과 비슷하게 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명식하는 방법입니다.

일반적으로 CPU 외부에 있는 메모리에 접근하는 것보다 CPU 내부에 있는 레지스터에 접근하는 것이 더 빠르기에 레지스터 주소 지정  방식은 직접 주소 지정 방식보다 빠르게 데이터에 접근할 수 있습니다.


 

레지스터 간접 주소 지정 방식

레지스터 간접 주소 지정 방식은 연산에 사용할 데이터를 메모리에 저장하고, 그 유효 주소를 저장한 레지스터를 오퍼랜드 필드에 명시하는 방법입니다.

유효 주소를 찾는 과정이 간접 주소 지정방식과 비슷하지만 메모리에 한 번만 접근한다는 차이가 있습니다.