감자는 아직 꿈을 꾼다.

[컴퓨터구조] 2. 데이터 본문

CS적 감자/컴퓨터 구조 & 운영체제

[컴퓨터구조] 2. 데이터

dreaming-potato 2024. 11. 20. 01:51

< 목 차 >

1. 0과 1로 숫자를 표현하는 방법

2. 리틀엔디안, 빅엔디안

3. 0과 1로 문자를 표현하는 방법

 


 

1. 0과 1로 숫자를 표현하는 방법

 

컴퓨터는 정보를 0과 1로 표현합니다.

 

😁정보 단위

0과 1을 나타내는 가장 작은 정보 단위를 비트(bit)라고 한다. 두 가지 정보를 표현합니다.

우리의 프로그램은 수많은 비트로 이루어져있습니다. 하지만 우리는 프로그램 파일의 크기를 몇비트라고 말하지않고,

메가바이트, 기가바이트 라는 말로 표현합니다.

여기서 바이트(Byte)는 8bit랑 대응되는 단위입니다.

 

1바이트를 1000개 묶은 게 1킬로바이트 (1KB), 1킬로바이트를 1000개 묶은 게 1메가바이트(1MB)

1메가바이트를 1000개 묶은 게 1기가바이트 (1GB), 1기가바이트를 1000개 묶은 게 1테라바이트 (1TB)

 

더보기

추가로 워드라는 개념이 있습니다.

워드(word)는 CPU가 정보를 한번에 처리할 수 있는 단위입니다.

워드의 크기는 32비트 아니면 64비트입니다. 인텔의 x86은 32비트 워드, x64 CPU는 64비트 워드

여기서 워드는 단위로 하프 워드,풀 워드, 더블 워드라고 불립니다.

 

🪟이진법 & 십진법 & 십육진법

 

이진법이 0과 1로 숫자를 표현하는 방식입니다. 사람이 일상생활에서 사용하는 단위는 십진법이죠.

하지만 우리는 10을 보고 이진법인지 십진법인지 구분을 할 수 없습니다.

그래서 구분하기 위해서 이진수는 숫자뒤에 (2) or 0b를 붙여서 구분합니다.

 

컴퓨터는 0과 1로 명령어들 부터 , 메모리 주소까지 전부 표현하는데 한 가지 단점이 있습니다.

사람이 봤을 때 0과 1로 이루어져있으면 너무 길어져서 가독성이 떨어진다는 점입니다.

이러한 점을 극복하기 위해서 실제로 십육진법으로 주로 확인합니다.

 

더보기

실제로 리버싱하거나, CTF, 시스템프로그래밍 등 어셈블리어를 확인할 때 16진법으로 봅니다.

또한 16진법을 사용해서 실제 프로그래밍에서 최댓값을 표현하기도 합니다.

Ox7fffffff -> 이렇게 표현합니다.

왜 앞이 7일까요?? -> 추후에 설명하겠습니다.

 

16진법은 0~15를 나타냅니다. 10부터는 10: A, 11 : B, 12: C, 13: D, 14: E, 15: F 이렇게 표현합니다.

2진수 -> 16진법

11001000 -> C8 이렇게 표현됩니다. 간단하게 4비트씩 끊어서 십진수로 변환하고 그걸 16진수로 대응하면 됩니다.

 

위에서 잠깐 언급했지만 int의 최댓값을 표현할 때 Ox7fffffff 으로 표현한다고 했습니다.

왜 전부 32가 1로 채워진 ffffffff이 아닐 까요? 이는 정수를 표현하는 방식인 signed 값으로 표현한 값이기 때문입니다.

그전에 2의 보수를 먼저 확인해봅시다.

🗽우리는 이진수의 음수를 어떻게 표현할까요??

그 방법은 2의 보수입니다. two's complement 라고 하죠.

2의 보수란? 어떤 수를 그보다 큰 2^n 에서 뺀 값 이라고 합니다.

하지만 이렇게 딱딱하게 생각하지말고 그냥 모든 0과 1을 뒤집고 거기에 1을 더하면 됩니다.

 

예를 들어서 4를 바꿔봅시다. 4비트만 있다고 가정하면 

0100 -> 1011 -> 1100 자 1100이 됬습니다. 어라 이건 12아니냐고요? 음수인지 확인해보는 방법으로는 

음수를 두번 즉 - ( - ( 수) ) 를 해서 확인해보는 방법으로 다시 2의 보수를 하면 

1100 -> 0011 -> 0100 자 원래대로 4가 되었으니 이 방식이 음수를 표현하는 방식인거는 알겠습니다.

더보기

2의 보수는 한계가 없을까? 

 

0을 2의 보수하면 다시 0입니다. 사실 이는 문제가 안되긴합니다 어처피 0은 부호의 의미가 없는 거고 

사실은 4비트라고 할 경우 10000이 되지만 실제에선 앞의자리가 버려서 문제가 딱히 없습니다.

또한 8비트의 경우 -128을 2의 보수를 취하면 128이 되어야하지만 실제로는 8비트에서 양수는 127까지만 표현되기에 -128로 다시 돌아옵니다.

하지만 컴퓨터는 어떻게 알까요? 이는 플래그 비트로 알 수있습니다.

여기서 이제 흔히 말하는 Signed / Unsigned 가 나오는 것입니다.

AI가 생성한 이미지 - 재미로만 봅시다!

우리가 일반적으로 코딩할 때 int값 쓰면 그 값은 Signed입니다 부호가 음수,양수가 존재하죠

위에서 말한데로 플래그 비트로 부호를 표현한다고 했는데

플래그 비트는 MSB(Most Significant Bit) 가장 왼쪽의 비트가 표현합니다.

0이면 양수,1이면 음수로 표현됩니다.

그래서 위에서 4를 2의보수 취하면 1100이 되었고 여기서 앞의 1은 음수비트인거죠.

(여기서는 4비트만 있다고 제한한 상황입니다)

읽는 방법은 간단하게 MSB는 부호비트, 나머지 비트 3 2^3 = 8 , 하고 현재 표현된 값인 4를 빼면 됩니다.

2^3 - 4 = 4, 예를 들어서 1000 이면 2^3 - 0 = 8 이므로 -8 인거죠.

- ( 2^N - ( 현재값) )

자 그러면 아까 위에서 0x7fffffff 기억이 나시나요? 이게 왜 양수의 최댓값인지 알겠나요?

귀찮지만 이진수로 써보면 0111 1111 1111 1111 1111 1111 1111 1111 입니다. 여기서 MSB인 0은 양수로 

나머지 31비트를 읽어서 표현하니 최대값인 2^31 -1이 표현된것입니다.

 

2. 리틀엔디안 / 빅엔디안

 

엔디안은 컴퓨터의 메모리 공간같은 1차원 공간에 연속된 숫자를 배열하는 방법입니다.

바이트를 배열하는 방식을 Byte Order라고 하며, 리틀엔디안 빅엔디안은 컴퓨터에 메모리를 저장할 바이트의 순서를 결정하는 방식입니다.

빅엔디안은 MSB부터 낮은 주소에 배열하는 방식입니다.

이미지와 같이 MSB인 OA부터 메모리의 낮은 주소에 배열 되는 방식으로 

MSB가 높은 주소이기에 빅 ( Big ) 엔디안 인것입니다.

 

빅엔디안은 보시다시피 사람이 읽기 편합니다.

그래서 주로 빅엔디안으로 메모리 주소를 확인합니다.

그리고 네트워크 프로토콜에서 주로 사용됩니다.

리틀엔디안은 반대로 LSB부터 메모리의 낮은 주소에 배열시키는 방식입니다.

 

x86/x64 CPU 아키텍처에서 사용되며 Intel에서 사용하므로 대부분 윈도우를 쓰는 컴퓨터에서 사용하는 방식입니다.

LSB가 가장 먼저와서 숫자의 값 계산에 더 직관적이고 효과적입니다.

 

더보기

시스템 간 데이터 교환시 , 만약 엔디안이 서로 다를 경우 엔디안 변환이 필요합니다

네트워크 통신  ( 빅  엔디안 ) <-> PC ( 리틀 엔디안 )

둘 중 어느 것이 좋다 이렇게 왈가왈부 하진 못합니다. 상황에 따라 달리지는 거죵

 

3. 0과 1로 문자를 표현하는 방법

 

우리는 숫자를 표현하는 방법에 대해서 알아봤습니다. 그러면 문자는 어떻게 표현할까요?

0과 1밖에 모르는 컴퓨터는 어떻게 문자를 이해할까요?

이에 중요한 건 문자집합,인코딩,디코딩 입니다.

AI가 생성한 디코딩 인코딩 재미로 봅시다 !

문자 집합이란 컴퓨터가 인식하고 표현할 수 있는 문자의 모음입니다.

문자 인코딩이란 문자를 컴퓨터가 인식할 수 있게 0과 1로 변환해주는 작업이고,

문자 디코딩은 0과 1인 정보를 사람이 읽을 수있게 문자로 변환하는 작업입니다.

 

😜아스키 코드 ( American Standard Code for Information Interchange) ASCII

 

참조 : 나무위키

아스키 코드는 코딩을 하다보면 자연스럽게 들어봤을 것입니다.

하지만 뭔지는 제대로 모를수도 있습니다. 실제로 코테를 할때 문자를 int로 바꿀 때 - '0' 이런식으로 써서 변환하기도 합니다. 잡설이 길었고, 아스키 코드는 영어로 표현 된 의미만 봐도 초창기 문자 집합으로 영어 알파벳, 아라비아 숫자, 일부 특수문자를 표현한 문자 집합입니다. 보시다시피 영어만 표현이 되어있습니다.

그래서 한글이나 다른 나라언어는 표현을 못합니다.

그리고 8비트로 표현하죠 char = 1바이트 , 하지만 1비트는 아스키 문자임을 나타내기 위한 패리티비트입니다.

그래서 2의 7승 128개의 문자를 표현할 수 있습니다.

 

위에서 char -> int를 변환할 때 방식을 소개했었는데 저렇게 가능한 이유가 문자 인코딩에서 글자에 부여된 값인 코드 포인트 때문에 가능한 것입니다. 코드포인트 값으로 A는 65인거죠. 십진수라고 생각하면 편할 것 같습니다. 엄밀하게는 다른걸로 알고있습니다.

하지만 한글도 표현못하고 128가지 문자는 표현하기에 너무 작습니다.

그래서 여러 나라들은 자신들의 언어를 0과 1로 표현하기 위한 문자집합과 인코딩 방식이 필요하다고 생각했습니다.

그래서 나온 인코딩이 EUC-KR입니다.

 

🥸EUC-KR 

 

한글은 초성,중성,종성의 조합으로 이루어져 있습니다.

그래서 한글 인코딩은 완성형과 조합형 인코딩 방식이 존재합니다.

완성형은 홍 길 동 이 각각 홍 : 1, 길 : 2 , 동 : 3 , 초성,중성,종성의 조합으로 이루어진 글자에 코드를 부여하는 방식입니다.

조합형은 홍이라는 글자에 ㅎ : 1 ㅗ : 2 ㅇ : 3 이렇게 각각 부여하는 방식이죠

 

여기서 EUC-KR은 완성형 인코딩입니다. 한글 한 단어에 2바이트 크기의 코드를 부여하죠.

( DB에 한글을 저장할 때도 2바이트씩 저장되는 경우도 있습니다. )

 

우리는 EUC-KR 덕분에 한글을 표현할 수 있게 되었지만, 모든 한글을 표현 하기엔 한계가 있었습니다.

뷁 이런 단어는 표현이 안되죠, 그래서 이름을 저장할 때 EUC-KR을 쓰는 사이트들이 인코딩이 깨지는 경우도 있었습니다.

그리고 이렇게 나라마다 인코딩 방식이 다르고 문자 집합이 다르면 언어별로 인코딩 방식이 달라지고

우리가 개발하는 웹서비스는 모든 인코딩 방식을 알아서 각자 처리해줘야 된다는 뜻입니다.

너무 번거롭지 않나요? 그래서 모드 나라의 문자집합과 인코딩을 통일하고자 나온 것들이 유니코드와 UTF-시리즈입니다.

 

🦏유니코드 & UTF-8,16,32 등

 

유니코드는 훨씬 다양한 한글을 표현하고 전세계 언어와 특수문자들을 대부분 포함하고있습니다.

UTF는 뭘까요? Unicode Transformation Format 말 그대로 유니코드를 인코딩 하는 방식입니다.

가장 대중적으로 사용하는 방식이 UTF-8입니다.

 

UTF-8은 1바이트부터 4바이트까지의 결과를 만들어 내는 데, 유니코드의 범위에 따라서 나뉘어집니다.

 

 

이정도만 알고있고 추가적으로 궁금한 부분은 따로 찾아보시는 걸 추천합니다.

 


여기까지가 2장 데이터가 끝났고, 약간의 시스템 프로그래밍 내용인 엔디안을 섞었습니다. 2의 보수에 관련된 내용도 아주 조금 추가를 했습니다.

이런 방식으로 계속 진행할 것 같습니다. 전공의 너무 복잡한 시프는 오히려 내용을 어지럽힐 것  같네요