-공부 목적의 어쩌구 포스트 입니다. 반박은 안 받습니다.-

 

Chapter 03-1

  • 앞서 컴퓨터는 "명령어를 처리하는 기계"라고 정의했었다.
    • 즉, 컴퓨터는 명령어가 있어야 유의미하다.
    • 우리 프로그래머들은 소스코드를 작성 해 컴퓨터에게 명령을 내린다. 다시 말해, 소스코드는 컴퓨터가 해야할 일을 작성한 매뉴얼이라고 봐도 된다.
  • 그러므로 챕터 3에서는 컴퓨터에게 가장 중요하다고 볼 수 있는 명령어에 대해 알아볼 것이다.
  • 명령어는 크게 두 가지로 구분할 수 있다.
1. 고급 언어
2. 저급 언어

고급 언어란...

  • 고급언어는 C, C++, JAVA, Python과 같은 프로그래밍 언어를 말한다.
  • 우리가 위와 같은 언어로 코딩을 하면 그 코드를 컴퓨터가 즉시 이해할 수 있는가?
    • 아니다!
  • 코드를 작성해 실행시키면 어떤 번역기가 튀어나와 고급언어컴퓨터가 알아들을 수 있는 언어로 변환시켜 준다. 이 언어가 저급언어다.

저급 언어란...

  • 위에서 저급 언어를 간단히 "컴퓨터가 알아들을 수 있는 언어"라 하였다.
  • 저급언어는 다시 두 가지로 나눌 수 있다.
    • 기계어
    • 어셈블리어
  • 기계어는 0과 1로 이루어진 언어를 말한다. 이를테면 다음과 같은 언어다.
    • 00111011 10110001 00000001 00000010
      • 이 기계어를 해석하면 "1 과 2를 더하라 "가 된다. (사실 지어낸것임)
    • 사람이 위의 기계어를 보고 어떤 명령어인지 쉽게 이해할 수 있을까?
    • 당연히 아니다.
    • 이에 답답함을 느낀 개발자들은 기계어를 편하게 이해하기 위해 어셈블리어를 개발한다.
  • 어셈블리어는 기계어를 "읽기 편한 형태로 번역한 언어"다.
    • 예를 들면, 다음과 같은 언어다.
      • mov eax, DWORD PTR [rbp-8]
      • add eax, 
    • 0과 1로 이루어진 기계어보다는 이해하기가 편하다. 최소한 알파벳으로 이루어져있고, 규칙만 알면 무엇을 말하고자 하는지 이해할 수는 있기 때문이다.
    • 어셈블리어는 임베디드 개발자, 게임 개발자, 정보 보안 분야 개발자들이 많이 이용한다.
    • 하지만 여전히 개발자들이 한 번에 보고 이해하기 어렵다는 느낌이 든다.
    • 그리하여 등장한 언어가 고급언어다.

 

위에서 저급언어기계어어셈블리어로 나누어진다고 했었다.

그럼 혹시 고급언어도 두 가지로 구분되려나 싶다. 맞다. 또 두가지로 나눌 수 있다.

 

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

이것이 고급언어의 두 가지 종류이다.

  • 흔히 Java는 컴파일 언어이고 Python은 인터프리터 언어라고 하는데 Java나 Python이나 사실은 컴파일과 인터프리터를 모두 사용한다. 어느 언어를 주로 사용하느냐고 묻는다면 Java는 컴파일, Python은 인터프리터 언어 라고 할 수 있지만.

컴파일 언어

  • 컴파일 언어는 프로그램을 실행할 때 컴파일러 라는 번역기가 작동해 프로그래머의 코드를 통째로 저급 언어로 번역해주는 언어다.
  • 소스코드 전체가 저급언어로 번역되고, 그 이후에 프로그램이 실행되기 때문에 코드 중간에 오류가 있다면 프로그램 자체가 실행되지 않는다.
  • 다음과 같은 예시가 컴파일의 예시다. 
    • ex. 원고를 받아서 번역 후 출판사에 넘겨주고, 출판사는 원고에 오류가 없는지 체크해 책으로 출판한다.

인터프리터 언어

  • 인터프리터 언어로 작성된 프로그램을 실행하면 인터프리터라는 번역기가 작동해 소스 코드를 한 줄씩 저급 언어로 번역하며 프로그램을 실행시킨다.
  • 코드 내에 오류가 있어도 그 직전의 row까지는 프로그램이 정상적으로 실행된다. 그리고 오류 row를 만나는 순간 오류를 뱉는다.
  • 다음과 같은 예시가 인터프리터의 예시다
    • ex. 번역가를 고용해 외국인이 한 마디를 할 때마다 번역을 해주는 상황

Chapter 03-2

이제 명령어를 자세히 들여다 볼 시간이다.

명령어는 연산 코드 필드와 오퍼랜드 필드로 이루어져 있다.

  • 연산 코드 필드에는 명령어가 수행할 연산(ex. 더해라, 빼라 등...)이 들어가 있다.
  • 오퍼랜드 필드에는 연산을 수행할 데이터 정보가 들어가있다.

위에서 간단히 정의하긴 했으나, 더 자세히 알아보도록 한다.

오퍼랜드

  • 오퍼랜드는 두 가지 방법으로 데이터를 담는다
    1. 연산에 사용되는 데이터를 직접 담음 (10, 20 등 직접적인 숫자의 경우)
    2. 연산에 사용되는 데이터가 저장된 주소를 담음 (변수 x 같은 경우)
  • 데이터는 메모리나 레지스터에 저장되므로 오퍼랜드는 메모리 주소나 레지스터 이름을 담을 수 있다.
  • 명령어는 여러개의 오퍼랜드를 가질 수 있다.
Q. 오퍼랜드는 왜 데이터를 직접 담지 않고 데이터가 저장된 주소를 담죠?

A. 명령어의 용량이 한정되어 있기 때문입니다.

  • 메모리주소보다 작은 용량의 명령어 하나에 데이터를 욱여넣는것보다 데이터를 가리키는 주소를 담는다면 명령어 하나 당 담을 수 있는 데이터가 메모리용량 만큼 늘어난다.

이제 이 데이터를 찾아 연산을 수행하게 해야한다.

데이터 위치 찾기

  • 데이터의 위치를 찾는 방법 또한 여러가지가 있는데 그 중 5가지를 소개하려 한다
  1. 즉시 주소 지정 방식
    • 연산에 사용할 데이터(이하 데이터)를 오퍼랜드 필드에 직접 명시하는 방법이다.
    • 빠르다는 장점이 있다
    • 데이터의 크기가 오퍼랜드 필드 용량 까지로 한정된다.
  2. 직접 주소 지정 방식
    • 데이터가 저장된 주소를 오퍼랜드에 명시하는 방법이다.
    • 주소의 크기가 오퍼랜드 필드 용량 까지로 한정된다.
  3. 간접 주소 지정 방식
    • 데이터가 저장된 주소의 주소를 오퍼랜드 필드에 명시하는 방법이다.
    • 주소의 크기에 제약을 받지 않는다는 장점이 있다.
    • 메모리에 두 번 접근해야하므로 시간이 오래 걸린다는 단점이 있다.
  4. 레지스터 주소 지정 방식
    • 직접 주소 방식과 비슷하다.
    • 그러나 메모리 주소가 아닌, 레지스터의 주소를 명시하는 방법이다.
    • 마찬가지로 주소의 크기가 오퍼랜드 필드 용량 까지로 한정된다.
  5. 레지스터 간접 주소 지정 방식
    • 데이터가 저장된 레지스터 주소의 주소를 오퍼랜드 필드에 명시하는 방법이다.
      • 레지스터의 주소는 메모리에 새로운 변수로 저장된다.
    • 간접 주소 지정 방식은 메모리에 두 번 접근하지만 이 방법은 메모리에 한번만 접근한다.
    • 그러므로 간접 주소 지정 방식보다 빠르다.

레지스터는 CPU안에 있고 메모리는 CPU바깥에 있다.

따라서, 물리적인 이유로 메모리를 거치는 것이 레지스터를 거치는 것 보다 느리다.