🧩 BE
home

컴퓨터가 이해하는 정보

Date
2025/06/08
Category
Computer Science
Tag
Computer Architecture
Detail

데이터의 단위

비트(bit) : 0과 1을 나타내는 가장 작은 정보의 단위
NN비트는 2N2^N개의 정보를 표현할 수 있다.
바이트(byte) : 비트를 묶은 단위
→ 1byte = 8bit. 따라서 1byte로는 282^8= 256개의 정보를 표현할 수 있다.
이전 단위 1000개를 묶은 단위는 kB, MB, GB, TB로 표현하며, 이전 단위 1024개를 묶은 단위는 kiB, MiB, GiB, TiB로 표현한다.
위의 정보 단위는 모두 프로그램 관점에서 바라본 단위이며, CPU 관점에서의 정보 단위로는 워드(word)가 있다. 워드란 CPU가 한 번에 처리할 수 있는 데이터의 크기를 의미한다.
현대 컴퓨터 대부분의 워드 크기는 32비트 또는 64비트이다.

소수의 오류

a = 0.1 b = 0.2 c = 0.3 if a + b == c: print("Equal") else: print("Not Equal")
Python
복사
위 코드를 실행하면 Equal이 출력될 것 같지만, 실제로는 Not Equal이 출력된다. 그 이유는 뭘까?
컴퓨터 내부에서는 부동 소수점(floating point) 방식을 이용하는데, 이 방식의 정밀도에 한계가 있기 때문이다.
예시로 10진수 123.123이라는 수를 m x 10n10^n의 꼴로 나타내면, 1.23123 x 10210^2 으로 표현할 수도 있고, 1231.23 x 10110^{-1}로 표현할 수도 있다. 여기서 2와 -1을 지수(exponent), 1.23123과 1231.23을 가수( significand)라고 한다.
2진수도 마찬가지로 m x 2n2^n의 꼴로 나타낸다. 컴퓨터는 2진수의 지수와 가수를 다음과 같은 IEEE 754라는 방식으로 저장한다.
가수의 정수부에는 1로 통일된 정규화한 수가 저장된다. 즉, 가수는 1.~~~의 형태를 띈다.
그럼 2지수2^{지수} x 1.~~~ 형태의 소수를 저장할 때는 지수에 해당하는 값과 가수의 소수 부분만 저장하면 된다.
컴퓨터가 지수를 저장할 때는 바이어스(bias)값이 더해져서 저장되며, 이때 바이어스 값은 2k12^{k-1}-1 이다.
만약 1101011.1010101 (10진수 107.6640625)이라는 수는 IEEE 754로 다음과 같이 저장된다. 0 / 10000101 / 10101110101010000000000
먼저 정규화를 해야하기에 1.1010111010101 x 262^6 으로 변환한다. 이후 지수 부분의 바이어스 값을 계산하면 2812^{8-1} -1 + 6 = 133 (2진수 10000101)이 되고, 나머지 소수 부분이 저장되게 된다.
여기서 유의할 점은 10진수 소수를 2진수로 표현할 때, 10진수 소수와 2진수 소수의 표현이 딱 맞아떨어지지 않을 수 있다는 점이다. 예시로 1/3이라는 분수를 m x 3n3^n꼴로 나타내고 싶다면 1 x 313^{-1}으로 표현하면 된다. 하지만 이 분수를 10진수로 표현하기는 어렵다. 0.33333… 처럼 무한히 많은 소수점이 필요하기 때문이다.
마찬가지로 10진수 0.1은 m x 10n10^n으로 간단히 나타낼 수 있지만, 이를 1.m x 2n2^n으로 표현하려면 무한히 많은 소수점이 필요할수도 있다. 때문에 부동 소수점 표현 방식에서 위와 같은 오차가 발생하는 것이다.

문자 표현하기

가장 기본적인 문자 집합에는 아스키(ASCII)가 있다. 하나의 아스키 문자를 표현하기 위해서는 8비트를 사용한다. 8비트 중 1비트는 패리티 비트라고 하여 오류 검출을 위해 사용되기에 실질적으로 문자는 7비트로 표현한다. 따라서 아스키는 128개의 문자를 표현할 수 있다. 문자에 대응한 0부터 127까지 고유한 수를 아스키 코드 라고 한다.
하지만 아스키 코드는 한글을 표기할 수 없고, 때문에 등장한 한글 인코딩 방식 중 하나가 EUC-KR이다. 이 방식은 아스키 문자를 표현할 때는 1바이트, 하나의 한글 글자를 표현할 때는 2바이트 크기의 코드를 부여한다. EUC-KR로 인코딩된 한글 글자 하나는 4자리 16진수로 나타낼 수 있다. but ‘쀓’ 같은 언어는 표현할 수 없다.
그래서 등장한 것이 유니코드(unicode) 문자 집합이다. 유니코드는 한글을 포함한 훨씬 많은 언어, 특수문자, 이모티콘까지 코드로 표현할 수 있는 통일된 문자 집합이고 현대 가장 많이 사용되는 표준 문자 집합이다.
이런 유니코드는 UTF-8, UTF-16, UTF-32 등 다양한 방법으로 인코딩할 수 있다.
문자 뿐만 아니라 이진 데이터까지 인코딩할 수 있는 방식으로 base64 인코딩이 있다. base64는 이미지 등 단순 문자 이외의 데이터까지 모두 아스키 문자 형태로 표현할 수 있다. base64는 64진법으로 나타내며, 64진수 하나를 표현하기 위해서는 262^6의 지수인 6비트가 필요하다.

명령어

명령어는 수행할 동작과 수행할 대상으로 이루어져 있다.
수행할 동작 : 연산 코드(opcode) || 연산자
수행할 대상 즉, 데이터나 데이터가 저장된 위치 : 오퍼랜드(operand) || 피연산자
오퍼랜드에는 사용될 데이터가 직접 명시되기 보다는 연산 코드에 사용될 데이터가 저장된 위치, 즉 메모리 주소나 레지스터 이름이 명시된다. 그래서 오퍼랜드를 주소 필드라고 부르기도 한다.
연산 코드의 대표적인 유형으로는 데이터 전송, 산술/논리 연산, 제어 흐름 변경, 입출력 제어가 있다.
기계어 : CPU가 이해할 수 있도록 0과 1로 표현된 정보
01010101 10100011 00010000
어셈블리어 : 기계어를 인간이 읽기 편한 형태로 단순 번역한 언어
push rbp, pop rbp, ret…
명령어의 종류와 생김새는 CPU마다 다르다. 때문에 여러 플랫폼에서 실행되는 프로그램을 개발할 때는 특정 CPU에만 의존적인 코드로 만들지 않아야 한다.

명령어 사이클

메모리 안에는 프로그램이 있고, 이 프로그램은 여러 명령어로 구성되어 있다. CPU는 이 메모리에서 명령어를 인출하고 실행하기를 반복하며 전체 프로그램을 실행한다. 이 과정에서 일정한 사이클이 생기는데, 이 주기를 명령어 사이클(instruction cycle)이라고 한다.
인출 사이클(fetch cycle) : 메모리의 명령어를 CPU로 가지고 오는 단계
실행 사이클(execution cycle) : 가져온 명령어를 CPU가 실행하는 단계
간접 사이클(indirect cycle) : 명령어를 실행하기 위해 한 번 더 메모리에 접근하는 단계
오퍼랜드 필드에 메모리 주소가 명시된 경우
인터럽트 사이클(interrupt cycle) : 인터럽트 발생 시 이를 처리하는 단계