본문 바로가기
혼자 공부하는 컴퓨터 구조+운영체제

3장 명령어

by lleesla 2024. 5. 18.

3-1 소스 코드와 명령어

  • 모든 소스 코드는 컴퓨터 내부에서 명령어로 변환된다.
  • 프로그래밍 언어가 어떻게 명령어가 되어 실행되는지 알아보자!

고급 언어와 저급 언어

  • 고급 언어는 ‘사람을 위한 언어’다.
  • 컴퓨터는 프로그래밍 언어를 이해할 수 없다.
  • 프로그래밍 언어는 컴퓨터가 이해하는 언어가 아닌 사람이 이해하고 작성하기 쉽게 만들어진 언어다.
  • 저급 언어는 ‘컴퓨터가 직접 이해하고 실행 할 수 있는 언어’다.
  • 컴퓨터가 이해하고 실행할 수 있는 언어는 저급 언어 뿐이다.
  • 그래서 고급 언어로 작성된 소스 코드를 저급 언어, 즉 명령어로 변환 되어야 한다.
  • 저급 언어는 두 가지 종류가 있다.
    • 기계어
      • 0과 1의 명령어 비트로 이루어진 언어
      • 이진수와 십육진수로 표현되는 기계어는 컴퓨터만을 위해 만들어진 언어이기 때문에 사람이 읽으면 의미를 이해하기 어렵다. (그래서 어셈블리어가 등장함)
    • 어셈블리어
      • 0과 1로 표현된 명령어(기계어)를 읽기 편한 형태로 번역한 언어
      • 기계어를 읽기 편하게 만든 저급 언어일 뿐이라 복잡한 프로그램을 만들긴 쉽지 않다.

  • 복잡한 프로그램을 만들기 위해선 고급 언어가 필요하다.
  • 개발자는 고급 언어로 소스 코드를 작성하면 알아서 저급 언어로 변환되어 잘 실행되어 저급 언어로 개발 할 일은 없다고 생각할 수 있다.
  • 하지만 하드웨어와 밀접하게 맞닿아 있는 프로그램을 개발하는 임베디드 개발자, 게임 개발자, 정보 보안 분야 등의 개발자는 어셈블리어를 많이 이용한다.
  • 또한 어셈블리어를 읽으면 컴퓨터가 어떤 과정으로 실행하는지, 관찰할 수 있다.

컴파일 언어와 인터프리터 언어

  • 고급 언어가 저급 언어로 변환하는 방식 2가지
    • 컴파일 방식
    • 인터프리트 방식
  • 컴파일 언어
    • 컴파일 방식으로 작동하는 프로그래밍 언어
    • 대표적인 컴파일 언어는 C언어가 있다.
    • 컴파일러에 의해 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어이고 이 과정을 컴파일이라고 한다.
    • 그리고 컴파일을 수행해 주는 도구를 컴파일러라고 한다.
    • 컴파일러는 개발자가 작성한 코드를 저급 언어로 컴파일 한다. 이때 오류를 하나라도 발견하면 컴파일에 실패한다.
    • 컴파일러를 통해 성공적으로 저급 언어로 변환된 코드를 목적 코드라고 한다.
  • 인터프리터 언어
    • 인터프리트 방식으로 작동하는 프로그래밍 언어
    • 대표적인 언어로 Python이 있다.
    • 인터프리터에 의해 소스 코드가 한 줄씩 실행되는 고급 언어다.
    • 소스 코드를 한 줄씩 저급 언어로 변환하여 실행해 주는 도구를 인터프리터라고 한다.
    • 컴파일 언어와 다르게 소스 코드를 한 줄씩 실행하기 때문에 n번째 줄에 문법 오류가 있더라도 n-1번째 줄까지는 올바르게 수행된다.
    • 목적 코드는 컴퓨터가 이해하고 실행할 수 있는 저급 언어인 반면, 인터프리터 언어는 마지막에 이를 때까지 한 줄씩 저급 언어로 해석하며 실행하기 때문에 인터프리터 언어가 컴파일 언어보다 느리다.

3-2 명령어의 구조

연산 코드와 오퍼랜드

  • 명령어는 연산코드와 오퍼랜드로 구성되어 있다.
  • 연산코드는 연산자, 오퍼랜드는 피연산자라고도 부른다.

  • 붉은 글씨가 연산 코드, 검은 글씨가 오퍼랜드
  • 오퍼랜드
    • 연산에 사용할 데이터가 저장된 위치
    • 숫자나 문자와 같이 연산에 사용할 데이터를 직접 명시하기 보다는 연산에 사용할 데이터가 저장된 위치, 즉 메모리 주소나 레지스터 이름이 담긴다.
    • 주소 필드라고 부른다.
    • 오퍼랜드는 명령어 안에 하나도 없을 수도 있고 여러 개 있을 수도 있다.
  • 연산코드
    • 명령어가 수행할 연산
      1. 데이터 전송
        1. MOVE : 데이터를 옮겨라
        2. STORE : 메모리에 저장하라
        3. LOAD (FETCH) : 메모리에서 CPU로 데이터를 가져와라
        4. PUSH : 스택에 데이터를 저장하라
        5. POP : 스택의 최상단 데이터를 가져와라
      2. 산술/논리 연산
        1. ADD / SUBTRACT / MULTIPLY / DIVIDE : 덧셈 / 뺄셈 / 곱셈 / 나눗셈을 수행하라
        2. INCREMENT / DECREMENT : 오퍼랜드에 1을 더하라 / 오퍼랜드에 1을 빼라
        3. AND / OR / NOT : AND / OR / NOT 연산을 수행하라
        4. COMPARE : 두 개의 숫자 또는 TRUE / FALSE 값을 비교하라
      3. 제어 흐름 변경
        1. JUMP : 특정 주소로 실행 순서를 옮겨라
        2. CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
        3. HALT : 프로그램의 실행을 멈춰라
        4. CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
        5. RETURN : CALL을 호출할 때 저장했던 주소로 돌아가라
      4. 입출력 제어
        1. READ (INPUT) : 특정 입출력 장치로부터 데이터를 읽어라
        2. WRITE (OUTPUT) : 특정 입출력 장치로 데이터를 써라
        3. START IO : 입출력 장치를 시작하라
        4. TEST IO : 입출력 장치의 상태를 확인하라

주소 지정 방식

  • 명령어의 오퍼랜드 필드에 메모리나 레지스터의 주소를 담는 경우가 많아 오퍼랜드 필드를 주소 필드라고 부른다. 여기서 의문! 그냥 <연산코드, 연산 코드에 사용될 데이터> 로 명령어를 구성하면 안될까?
  • 안된다! 명령어 길이 때문이다. 명령어가 n비트로 구성되어있고 연산코드 필드가 m비트라면 오퍼랜드 필드의 길이는 연산 코드만큼의 길이를 뺀 n-m 비트가 된다.
  • 그렇게 되면 오퍼랜드 필드로 표현할 수 있는 정보의 가짓수는 2-주소 명령어에서는 2^6개 3-주소 명령어에서는 2^4개 밖에 되지 않는다.
  • 하지만 오퍼랜드 필드 안에 메모리 주소가 담긴다면 표현할 수 있는 데이터의 크기는 하나의 메모리 주소에 저장할 수 있는 공간만큼 커진다.
  • 연산 코드에 사용할 데이터가 저장된 위치, 즉 연산의 대상이 되는 데이터가 저장된 위치를 유효 주소라고 한다.
  • 오퍼랜드 필드에 데이터가 저장된 위치를 명시할 때 연산에 사용할 데이터 위치를 찾는 방법을 주소 지정 방식이라고 한다.
  • 주소 지정 방식은 유효 주소를 찾는 방법이다.
  • 즉시 주소 지정 방식
    • 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시하는 방식
    • 가장 간단한 형태의 주소 지정 방식
    • 데이터의 크기가 작아지는 단점이 있지만 연산에 사용할 데이터를 메모리나 레지스터로부터 찾는 과정이 없기 때문에 빠르다.
  • 직접 주소 지정 방식
    • 오퍼랜드 필드에 유효 주소를 직접 명시하는 방식
    • 오퍼랜드 필드에서 표현할 수 있는 데이터의 크기는 즉시 주소 지정방식보다 커졌지만 여전히 유효 주소를 표현할 수 있는 범위가 연산 코드의 비트 수만큼 줄어들었다.
    • 표현할 수 있는 오퍼랜드 필드의 길이가 연산 코드의 길이만큼 짧아져 표현할 수 있는 유효 주소에 제한이 생길 수 있다.
  • 간접 주소 지정 방식
    • 유효 주소의 주소를 오퍼랜드 필드에 명시한다.
    • 직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 넓어졌다.
    • 다만 두번의 메모리 접근이 필요하기 때문에 앞선 방식들보다 느리다.
  • 레지스터 주소 지정 방식
    • 직접 주소 지정 방식과 비슷하게 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시하는 방법이다.
    • 일반적으로 CPU 외부에 있는 메모리에 접근하는 것보다 CPU 내부에 있는 레지스터에 접근하는 것이 더 빠르다.
    • 그러므로 레지스터 주소 지정 방식은 직접 주소 지정 방식보다 빠르게 데이터에 접근할 수 있다.
    • 다만 표현할 수 있는 레지스터 크기에 제한이 생길 수 있다.
  • 레지스터 간접 주소 지정 방식
    • 연산에 사용할 데이터를 메모리에 저장하고 그 주소를 저장한 레지스터를 오퍼랜드 필드에 명시하는 방법
    • 유효 주소를 찾는 과정이 간접 주소 지정 방식과 비슷하지만, 메모리에 접근하는 횟수가 한 번으로 줄어든다는 장점이 있다.
    • 레지스터 간접 주소 지정 방식은 간접 주소 지정 방식보다 빠르다.

즉시 주소 지정 방식 연산에 사용할 데이터

직접 주소 지정 방식 유효 주소 (메모리 주소)
간접 주소 지정 방식 유효 주소의 주소
레지스터 주소 지정 방식 유효 주소 (레지스터 이름)
레지스터 간접 주소 지정 방식 유효 주소를 저장한 레지스터

*좀 더 알아보기

  • 스택과 큐
    • 스택
      • 한쪽 끝이 막혀있는 통과 같은 저장 공간
      • 막혀있지 않은 쪽으로 데이터를 차곡차곡 저장하고, 저장한 자료를 빼낼 때는 마지막으로 저장한 데이터부터 빼낸다.
      • 후입선출이라는 점에서 LIFO(리포)자료 구조라고 부른다.
      • 이때 스택에 새로운 데이터를 저장하는 명령어가 PUSH, 스택에 저장된 데이터를 꺼내는 명령어가 POP이다.
      • 양쪽이 뚫려 있는 통과 같은 저장 공간
      • 한쪽으로는 데이터를 저장, 다른 한쪽으로는 저장한 순서대로 데이터를 빼낸다.
      • 가장 먼저 저장된 데이터부터 빼내는 데이터 관리방식(선입선출)이라는 점에서 FIFO 자료구조라고도 부른다. 

 

- 고급 언어는 사람이 이해하고 작성하기 쉽게 만들어진 언어다.
- 저급 언어는 컴퓨터가 직접 이해하고 실행할 수 있는 언어다.
- 저급 언어는 0과 1로 이루어진 명령어로 구성된 기계어와 기계어를 사람이 읽기 편한 형태로 변역한 어셈블리어가 있다.
- 컴파일 언어는 컴파일러에 의해 소스 코드 전체가 저급 언어로 변환되어 실행되는 언어다.
- 인터프리터 언어는 인터프리터에 의해 소스 코드가 한 줄 씩 저급 언어로 변환되어 실행되는 언어다.
- 명령어는 연산 코드와 오퍼랜드로 구성된다. - 연산 코드는 명령어가 수행할 연산을 의미한다.
- 오퍼랜드는 연산에 사용할 데이터 또는 연산에 사용할 데이터가 저장된 위치를 의미한다.
- 주소 지정 방식은 연산에 사용할 데이터 위치를 찾는 방법이다.

'혼자 공부하는 컴퓨터 구조+운영체제' 카테고리의 다른 글

6장 메모리와 캐시 메모리  (1) 2024.06.04
5장 CPU 성능 향상 기법  (0) 2024.06.04
4장 CPU의 작동 원리  (1) 2024.05.19
2장 데이터  (0) 2024.05.17
1장 컴퓨터 구조 시작하기  (0) 2024.05.10