본문 바로가기

Computer Structure

컴퓨터 구조 정리 (2)

반응형

문자 집합과 인코딩

  • 0과 1로 문자를 표현하기 전에 알아야 할 세 가지는 문자 집합, 인코딩, 디코딩 이다.
  • 컴퓨터가 인식하고 표현할 수 있는 문자의 모음을 문자집합(character set)이라고 한다.
  • 문자를 컴퓨터가 이해할 수 있게 0과 1로 변환하는 과정을 문자 인코딩(character encoding)이라 한다.
  • 0과 1로 이루어진 문자 코드를 사람이 이해 할 수 있는 문자로 변환하는 과정을 문자 디코딩(character decoding)이라 한다.

 

아스키 코드(ASCII; American Sandard Code for Information Interchange)

  • 초창기 문자 집합 중 하나로, 알파벳, 아라비아 숫자, 일부 특수문자를 표현한다.
  • 각각 7비트로 표현, 7비트로 표현할 수 있는 가짓수는 2의7승, 128개의 문자를 표현
  • 8비트의 확장 아스키가 등장하기도 했지만 256개여서 턱없이 부족했다.

 

EUC-KR

  • 영어와 달리 한글은 각음절 하나하나가 초성, 중성, 종성의 조합으로 이루어져 있어 한글에는 완성형, 조합형이 존재한다.
  • 완성형 인코딩은 초성, 중성, 종성으로 이루어진 글자에 고유한 코드를 부여하는 인코딩 방식
    • '가' 는 1, '나'는 2 식으로 인코딩 하는 방식
  • 조합형 인코딩은 초성을 위한 비트열, 중성, 종성을 위한 비트열을 할당하여 조합으로 완성하는 인코딩 방식
    • '강'일때 'ㄱ'는 0010(2), 'ㅏ'는 0011(2), 'ㅇ'은 0001 00011으로 인코딩하는 방식
    • 초성, 중성, 종성이 모두 결합된 한글 단어에 2바이트 크기의 코드를 부여한다.

 

유니코드와 UTF-8

  • 유니코드는 여러 나라의 문자들을 광범위하게 표현할 수 있는 통일된 문자집합, UTF-8, UTF-16, UTF-32는 유니코드 문자의 인코딩 방식이다.
  • UTF-8은 1바이트 부터 4바이트까지의 인코딩 결과를 만들어 낸다.

 

고급언어와 저급언어

  • 사람이 이해하고 작성하기 쉽게 만들어진 언어를 고급 언어(high-level programming language)라고 한다.
  • 컴퓨터가 직접 이해하고 실행 할 수 있는 언어를 저급 언어(low-level programming language)라고 한다.
  • 컴퓨터가 이해하고 실행할 수 있는건 저급 언어뿐이기 때문에, 고급 언어로 작성된 소스 코드가 실행되려면 저급언어 즉 명령어로 변환되어야 한다.
  • 저급언어에는 두 가지 종류인 기계어와 어셈블리어가 있다.
  • 기계어(machine code)란 0과 1의 명령어 비트로 이루어진 언어이다.
  • 0과 1로 표현된 명령어(기계어)를 일기 편한 형태로 번역한 언어가 어셈블리어(assembly language)이다.
기계어 어셈블리어
0101 0101  push rbp
0101 1101  pop rbp
1100 0011 ret

 

하드웨어와 밀접하게 맞닿아 있는 임베디드 개발자, 게임 개발자, 정보 보안 분야 등의 개발자는 어셈블리어를 많이 이용한다고 한다.

 

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

  • 컴파일 방식으로 작동하는 프로그래밍 언어를 컴파일 언어라고 한다.
  • 컴파일 언어는 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어이다.
  • 대표적 컴파일 언어로는 C가 있다.
  • 저급 언어로 변환되는 과정을 컴파일(compile)이라고 하며, 컴파일을 수행해주는 도구를 컴파일러(complier)라고 한다.
  • 컴파일러는 소스 코드 내에서 오류를 발견하면 해당 소스 코드는 컴파일에 실패한다.

 

  • 인터프리트 방식으로 작동하는 프로그래밍 언어를 인터프리터 언어라고 한다.
  • 인터프리터 언어는 인터프리터에 의해 소스 코드가 한 줄 씩 실행되는 고급언어이다.
  • 대표적인 인터프리터 언어는 Python이 있다.
  • 소스 코드를 한 줄씩 저급 언어로 변환하여 실행해주는 도구를 인터프리터(interpreter)라고 한다.
  • 컴퓨터와 대화하듯 소스 코드를 한 줄 씩 실행하기 때문에 소스 코드 전체를 저급 언어로 변환하는 시간을 기다릴 필요가 없다.
  • 한 줄씩 실행하기 때문에 소스 코드 N번째 줄에 문법 오류가 있더라고 N-1번째 줄까지는 올바르게 수행된다.
  • 일반적으로는 인터프리터 언어는 컴파일 언어보다 느리다. 컴파일을 통해 나온 결과물, 목적코드는 컴퓨터가 이해하고 실행할 수 있는 저급언어인 반면, 인터프리터 언어는 소스코드 마지막에 이를 때까지 한 줄씩 저급언어로 해석하며 실행해야 하기 때문이다.
  • Python도 컴파일을 하지 않는 것은 아니며, Java의 경우 저급 언어가 되는 과정에서 컴파일과 인터프리트를 동시에 실행한다.

 

목적 파일 vs 실행 파일

  • 이미지로 이루어진 파일을 이미지 파일이라 부르고, 텍스트로 이루어진 파일을 텍스트파일이라고 부르듯 목적 코드로 이루어진 파일을 목적 파일이라고 부른다.
  • 마찬가지로 실행 코드로 이루어진 파일을 실행파일이라고 부른다.
  • 윈도우의 .exe 확장자를 가진 파일이 대표적 실행 파일이다.
  • 목적 파일과 실행 파일은 같은 의미가 아니다.
  • 목적 코드가 실행 파일이 되기 위해서는 링킹(linking)이라는 작업을 거쳐야 한다.
    • helper.c와 main.c라는 두 개의 소스 코드가 있다.
    • 소스 코드 내부에 아래와 같은 내용이 있다고 가정해보자.
    • 1. helper.c 는 HELPER_더하기 기능
    • 2. main.c 는 helper.c에 구현된 HELPER_더하기 기능
    • 이들을 컴파일 하면 각각의 소스 코드로부터 목적 코드가 생성된다.
    • main.c를 컴파일해서 실행하면 외부 기능인 helper와 연결 짓는 작업이 필요한다. 이 작업이 링킹이다.
  • 링킹 작업까지 거치면 비로소 하나의 실행 파일이 만들어진다.

 

연산 코드와 오퍼랜드

  • 명령어는 연산 코드와 오퍼랜드로 구성되어 있다.
  • '명령어가 수행할 연산'을 연산 코드(operation code)라 한다.
  • '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'를 오퍼랜드(operand)라 한다.
  • 연산 코드는 연산자, 오퍼랜드는 피연산자라고도 부른다.
  • 연산 코드가 담기는 영역을 연산 코드 필드라고 하며, 오퍼랜드가 담기는 영역을 오퍼랜드 필드라고 한다.

 

오퍼랜드

  • '연산에 사용할 데이터' 또는 '연산에 사용할 데이터가 저장된 위치'를 의미한다.
  • 오퍼랜드 필드에는 숫자, 문자 등을 나태내는 데이터 또는 메모리나 레지스터 주소가 올 수 있다.
  • 연산에 사용할 데이터를 직접 명시하기보다는, 연산에 사용할 데이터가 저장된 위치, 즉 메모리 주소나 레지스터 이름이 담긴다. 그래서 오퍼랜드 필드를 주소 필드라고 부르기도 한다.
  • 어셈블리어 예시
mov eax, 0 오퍼랜드가 두 개인 경우
pop rbp 오퍼랜드가 한 개인 경우
ret   오퍼랜드가 없는 경우

 

  • 오퍼랜드가 하나도 없는 명령어를 0-주소 명령어
  • 오퍼랜드가 하나인 명령어를 1-주소 명령어
  • 오퍼랜드가 세 개인 명령어를 3-주소 명령어라고 한다.

 

연산 코드

  • 연산 코드는 명령어가 수행할 연산을 의마한다. '더해라', '빼라', '저장해라' 등
  • 연산 코드 종류는 매우 많지만, 크게 네 가지로 나눌 수 있다.
    • 데이터 전송
      • 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) : 특정 입출력 장치로부터 데이터를 읽어라
      • WRITE(OUTPUT) : 데이터를 써라
      • START IO : 입출력 장치를 시작하라
      • TEST IO : 입출력 장치의 상태를 확인하라

 

주소 지정 방식

  • '명령어의 오퍼랜드 필드에 메모리나 레지스터의 주소를 담는 경우가 많다. 그래서 오퍼랜드 필드를 주소 필드라고 부르기도 한다.'
  • 연산 코드, 연산 코드에 사용될 데이터 형식으로 명령어를 구성하지 않는 이유는 명령어 길이 때문이다.
  • 하나의 명령어가 n비트로 구성되어 있고, 연산 코드 필드가 m비트라고 가정하면 오퍼랜드 필드에 가장 많은 공간을 할당할 수 있는 1-주소 명령어라 할지라도 오퍼랜드 필드의 길이는 연산 코드만큼의 길이를 뺸 n-m비트가 된다.
  • 2-주소 명령어, 3-주소 명령어라면 오퍼랜드 필드의 크기는 더욱 작아진다.
  • 한마디로 필드에 명령어를 바로 저장하면 오퍼랜드 필드로 표현할 수 있는 정보의 가짓수는 2의4승개 밖에 없다.
  • 하지만 만약 오퍼랜드 필드 안에 메모리 주소가 담긴다면 표현할 수 있는 데이터의 크기는 하나의 메모리 주소에 저장할 수 있는 공간만큼 커진다.
  • 한 주소에 16비트를 저장할 수 있는 메모리가 있으면, 메모리에 데이터를 저장하고, 오퍼랜드 필드 안에 해당 메모리 주소를 명시하면 표현할 수 있는 정보의 가짓수가 2의16승으로 확 커진다.
  • 오퍼랜드 필드에 데이터가 저장된 위치를 명시할 때 연산에 사용할 데이터 위치를 찾는 방법을 주소지정방식(addressing mode)라고 한다.
  • 주소 지정방식은 유효 주소를 찾는 방법이다.

 

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

  • 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시하는 방식
  • 가장 간단한 형태의 주소 지정방식
  • 데이터의 크기가 작아지는 담점이 있음
  • 연산에 사용할 데이터를 메모리나 레지스터로부터 찾는 과정이 없기 때문에 다른 주소 지정방식들 보다 빠르다.

 

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

  • 오퍼랜드 필드에 유효 주소를 직접적으로 명시하는 방식
  • 오퍼랜드 필드에서 표현할 수 있는 데이터의 크기는 즉시 주소 지정방식보다 커진다.
  • 하지만 유효 주소를 표현할 수 있는 범위가 연산 코드의 비트 수만큼 줄어든다.
  • 표현할 수 있는 오퍼랜드 필드의 길이가 연산 코드의 길이만큼 짧아져 표현할 수 있는 유효 주소에 제한이 생길 수 있다.

 

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

  • 유효 주소의 주소를 오퍼랜드 필드에 명시한다.
  • 직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 넓어진다.
  • 하지만 두 번의 메모리 접근이 필요하기 때문에 일반적으로 느리다.

 

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

  • 직접 주소 지정 방식과 비슷하게 연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 직접 명시한다.
  • CPU 외부에 있는 메모리 접근 보다 CPU 내부에 있는 레지스터에 접근하는 것이 더 빠르다.
  • 레지스터 주소 지정 방식은 더 빠르지만 표현할 수 있는 레지스터 크기에 제한이 생길 수 있다.

 

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

  • 연산에 사용할 데이터를 메모리에 저장하고,그 주소를 저장한 레지스터를 오퍼랜드 필드에 명시한다.
  • 간접 주소 방식과 비슷하지만 메모리에 접근하는 횟수가 한 번으로 줄어든다는 장점이 있다.
  • 간접 주소 지정 방식보다 빠르다.

 

 

오퍼랜드 필드에 명시하는 값을 정리해 보면 아래와 같다.

  • 즉시 주소 지정 방식 : 연산에 사용할 데이터
  • 직접 주소 지정 방식 : 유효 주소(메모리 주소)
  • 간접 주소 지정 방식: 유효 주소의 주소
  • 레지스터 주소 지정 방식: 유효 주소(레지스터 이름)
  • 레지스터 간접 주소 지정 방식 : 유효 주소를 저장한 레지스터

 

 

 

 

'Computer Structure' 카테고리의 다른 글