본문 바로가기
컴퓨터 구조

[컴퓨터 구조] 명령어

by GroovyCat11 2023. 7. 20.

이번에는 명령어에 대해서 알아보도록 하겠습니다.

컴퓨터는 우리가 작성한 소스코드를 읽어서 프로그램을 실행하는데,

이때 소스코드를 그냥 바로 해석하지 않습니다.

컴퓨터는 소스코드를 컴퓨터가 이해하기 쉬운 형태로 변환해서 읽습니다.

우리는 소스코드를 고급 언어, 그리고 컴퓨터가 이해하기 쉬운 형태를 저급 언어라고 부릅니다.

고급 언어 - 개발자가 이해하기 쉬운 언어 

ex) C, C++, Java, Python, C# 등등

저급 언어 - 컴퓨터가 이해하고 실행하는 언어

ex) 기계어, 어셈블리어

 

그러면 고급언어와 저급언어에 대해서 좀 더 자세히 알아봅시다.


고급 언어(High-Level Language)

고급언어는 크게 2가지 형태의 언어로 존재한다.

 

컴파일 언어(Compile Language)

  • 컴파일러(Compiler)에 의해 저급 언어로 변환하는 것을 컴파일(Compile)이라고 하는데 이 컴파일 과정을 사용하는 고급 언어
  • 이때 컴파일된 후 생성된 저급 언어를 목적 코드라고 부른다.
  • 만약 소스 코드의 문제가 있다면 소스 코드가 실행되지 않음
  • 대표적인 언어: C, C++, Java, C# 등

컴파일 언어

 

인터프리트 언어(Interpreted Language)

  • 인터프리터(Interpreter)에 의해 한 줄씩 실행되는 고급 언어
  • 소스 코드 전체가 저급 언어로 변환되기까지 기다릴 필요가 없음
  • 컴파일 언어에 비해 실행 속도가 조금 느림(코드 작성해서 실행하면 인터프리터에 한 줄씩 읽어서 명령하기 때문)
  • 소스 코드의 문제가 있다면 문제가 되는 부분 이전 코드들은 실행되고 문제되는 부분에서 중지
  • 대표적인 언어: Java, Javascript, Python, SQL 등

※ Java는 컴파일과 인터프리터가 둘 다 존재함

 

 

저급언어(Low-Level Language)

 

기계어

  • 2진수로 이루어진 명렁어로 구성된 저급 언어
  • 16진수로도 표현할 수 있음

어셈블리어(Assembly Language)

  • 2진수로 이루어진 기계어를 읽기 편한 형태로 번역한 저급 언어
  • 컴퓨터 아키텍처에 따라 코드가 달라짐(intel, amd, mac 등)

다음 그림은 NASM(어셈블러) x86에서 사용되는 어셈블리어로 구현한 Hello World! 출력 프로그램이다.

Hello World! 출력 프로그램 어셈블리어[1]

 

그러면 이제 명령어 구조에 대해 살펴보도록 합시다!


명령어는 크게 이런 의도가 들어있습니다.

어떤 대상에게 이렇게 해라! → 대상, 실행

컴퓨터의 명령어도 다를바 없습니다.

 

명령어 구조

 

명령어는 크게 연산코드오퍼랜드로 구성되어 있습니다.

 

연산코드

  • 수행할 연산
  • CPU의 종류마다 다름(intel, amd 등)
  • 데이터 전송, 산술/논리 연산, 제어 흐름 변경, 입출력 제어

오퍼랜드

  • 연산에 사용될 데이터 혹은 연산에 사용될 데이터가 저장된 위치(주소 필드)
  • 오퍼랜드는 없는 경우도 있으며 1개, 2개 혹은 다중으로 구성될 수 있음

오퍼랜드는 주로 주소 필드인 경우가 많다.

왜 직접적인 데이터값이 아니라 데이터가 저장된 위치가 선언되는 것인가?

왜냐하면 오퍼랜드에 표현할 수 있는 데이터 크기의 범위가 제한적이기 때문입니다.

오퍼랜드 데이터 표현 범위

그래서 오퍼랜드에 데이터가 저장된 위치 즉, 메모리 주소 값을 선언하게 되면 어떻게 되는가?

기존 오퍼랜드에서 표현할 수 있는 범위가 아니라 해당 데이터가 저장된 메모리 주소로 가게 되면 

연산에 사용할 데이터의 표현 범위가 넓은 상태로 저장되는 거죠.

 

위 그림의 1-주소 명령어를 예시로 본다면

오퍼랜드에 20번지라고 선언되어 있으면 20번지에 해당하는 메모리로 가게 됩니다.

그러면 현재 명령어로 쓰이는 공간의 총 데이터 범위는 2^16 이니까 해당 20번지의 데이터 표현 범위도 2^16이 되는 겁니다. 

따라서 오퍼랜드에는 주로 메모리 주소 값을 선언하는 것이 대부분입니다.

이때의 메모리 주소 값을 다른 용어로 유효 주소(effective address)라고 합니다.


근데, 이러한 주소를 지정하는 방식도 나뉩니다.

이를 명령어 주소 지정 방식(addressing modes)라고 합니다.

 

즉시 주소 지정 방식(immediate addressing mode)

  • 연산에 사용할 데이터를 주소 필드(오퍼랜드)에 직접 명시
  • 가장 간단한 형태의 지정 방식
  • 연산에 사용할 데이터의 크기가 작아질 수 있지만, 빠름

직접 주소 지정 방식(direct addressing mode)

  • 주소 필드에 유효 주소를 직접적으로 명시
  • 유효 주소를 표현할 수 있는 크기가 연산 코드만큼 줄어듦

간접 주소 지정 방식(indirect addressing mode)

  • 주소 필드에 유효 주소의 주소를 명시
  • 다른 주소 지정 방식들에 비해 속도가 느림 → 유효 주소의 주소이다 보니 한번 더 거침

레지스터 주소 지정 방식(register addressing mode)

  • 연산에 사용할 데이터가 저장된 레지스터 명시
  • 다른 주소 지정 방식에 비해 빠름 → 메모리보다 레지스터에 접근하는게 빠름

레지스터 간접 주소 지정 방식(register indirect addressing mode)

  • 연산에 사용할 데이터를 메모리에 저장
  • 해당 유효 주소를 레지스터에 명시하고 명시된 레지스터를 주소 필드에 명시

지금까지 명령어에 대해서 살펴봤습니다.

다음에는 컴퓨터의 심장이라고 할 수 있는 CPU의 각 부품들과 동작 방식에 대해서 알아보겠습니다.

길면 길고 짧으면 짧은 글 봐주셔서 감사드립니다.

오늘도 도움이 되셨기를 바라겠습니다!


[참고문헌]

[1] 어셈블리어 - 위키백과, 우리 모두의 백과사전 (wikipedia.org)

 

어셈블리어 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 어셈블리어(영어: assembly language) 또는 어셈블러 언어(assembler language)[1]는 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어이다. 컴퓨터 구조에 따

ko.wikipedia.org