2013년 11월 26일 화요일

컴퓨터에서 숫자가 저장될 때, 바이트 단위의 역순으로 저장되는 이유

주제: 컴퓨터에서 숫자가 저장될 때, 바이트 단위로 역순으로 저장되는 이유는 무엇인가?
예를 들어 2002라는 10진수를 16진수로 바꾸면 7D2가 된다
이것을 파일로 직접 기록하거나 메모리에 저장한 후에 살펴보면 D207으로 바이트 단위로 역으로 바뀌어 저장된다.
이렇게 저장되는 이유는 무엇인가?

작성일: 2002년 8월30일(금) 첫 작성.
작성자: 조현교(mrbig, linux0@hanmail.net)

본문:

이 이야기는 도스 시절 게임에디트를 하기 위해 헥스에디터가 가능한 프로그램(PCTOOLS4.x시리즈, HE.COM-헥스코드에디터, Norton Diskedit 등..)을 이용해서 바이너리 상태로 저장된 세이브 파일을 직접 수정하던 시대로 되돌아간다.

기억을 더듬어 보건대 본인이 이짓을 처음으로 하게 된 게임은 삼국지3로 기억한다. (다른 게임으로는 슈퍼대전략, 삼국지외전2, 어스토니시아 스토리 등등.. 삼국지는 파워업키트가 나온 이후로 하지 않았던걸로 기억한다.)

당시 게임을 하다가 너무 짜증남과 동시에 능력치를 처음부터 바꾸면 어떨까라고 고민하던중.
세이브 파일을 직접 수정하면 어떨까라고 생각했다.
그래서 게임 상에 등장하는 수치들을 모두 연습장에 옮긴 후, 공학용 계산기를 이용해서 16진수로 바꾸고 pctools 4.x버전을 이용해서 찾아보았다. 먼저 내가 저장한 데이터가 있는 섹터를 찾았고 이 부근에서 16진수로 바꾼 수치들을 검색해보았다.
놀랍게도 능력치 수치가 찾아졌고 수정후 저장하고 게임에 들어가니
바뀌어 있는 것이었다!

그런데 조금 큰 숫자.. 삼국지3의 경우 금의 양 같은 경우는 255라는 숫자를 넘어가니 찾아지지 않는것이었다.

나는 내가 저장한 부분의 데이터가 있는 곳을 탐색해서 하나씩 숫자를 10진수로 바꾸어보았다. 그리고 깨달은 것이 있다.

컴퓨터에서는 16진수를 바이트 단위로 거꾸로 기록한 것이었다.

예를 들어 본인이 서주에서 금을 30000 가지고 있었다면 이 수를 16진수로 변환하면 75 30 이 된다. 하지만 실제 기록될 때는 30 75로 뒤바뀐채로 기록된다.

여기서 1바이트는 8bit이고 4bit는 16진수로 0~F(즉 0~15) 까지 표현가능하고 곧 8bit는 00 ~ FF(즉 0 ~ 255)까지 표현가능하다.

10진수 254000 가 컴퓨터에 기록될 경우:
254000(10) -> 03 E0 30(16) -> 30 E0 03(16)
으로 뒤바뀌어 저장된다.(바이트 단위로 뒤바뀜, 1바이트는 위에서 설명했듯이 8bit이기 때문에 16진수로 FF 최대 255가 된다)

이런 방식을 역워드 방식이라고 부른다.

보다 정확한 용어로는 Little Endian 이라고 부른다.

이런 저장방식의 차이는 CPU 의 구조에서 오는 것이다.

대부분의 RISC프로세서나, 모토롤라 프로세서의 경우에는 이런 방식으로 저장되지 않는다. 우리가 읽는 그대로 03 E0 30은 그냥 03 E0 30으로 순서대로 저장된다. 이런 방식을 Big Endian이라고 부른다.

하지만 Intel의 x86계열의 프로세서들이나 DEC의 Alpha칩의 경우에는 Little Endian 으로 데이터가 저장된다.

Little Endian은 자리수가 낮은 숫자를 먼저 저장하는 방식이며,
Big Endian은 자리수가 높은 숫자를 먼저 저장하는 방식이다.

03 E0 30의 경우 Little Endian은 자리수가 낮은 숫자, 즉 30이 먼저 기록되고 그 다음 E0, 다음 03이 저장되지만 Big Endian은 높은 자리수인 03 -> E0 -> 30 순서대로 저장된다.

왜 Intel의 프로세서들과 DEC의 알파칩들은 Little Endian 방식을 이용하여 알아보기 불편하게 저장하는 것일까?

그 이유는 다음과 같다.

Little Endian방식의 경우 숫자의 자리수가 증가하게 될 경우의 연산에 대해 약간 빠르게 동작할 수 있다는 것이다.

예를 들어보자.

Big Endian 방식에서 50000 이라는 숫자를 저장한다고 가정하자.

이 숫자는 16진수로 C3 50 이다. Big Endian방식이기 때문에 그대로 저장된다.

이 때 65536 이라는 숫자를 50000에 더하면 115536 이 되고
16진수로는 01 C3 50 이 된다. 이 숫자로 바꾸기 위해서는 먼저 C3과 50을 저장공간의 오른쪽으로 옮겨야 되며 옮긴 후에 왼쪽의 빈 공간에 01을 기록하여야만한다.

이 것을 Little Endian 방식으로 저장하게 되면

50000 이라는 숫자는 C3 50 이 아닌 50 C3으로 저장되게 되고

여기에 65536을 더해서 115536으로 바꾸어 기록할 때, 단순히 50 C3 의 오른쪽에 01을 새로 써주기만하면 된다.

이런 식으로 특정한 연산에 대해 아주 단순해 질 수 있다는 것이 Little Endian방식의 장점이다. 물론 새로 기록되는 수가 완전히 다른 것이면 별차이가 없어진다. 그리고 컴퓨터 메모리의 구조상 추상적으로 말하자면 왼쪽에서 오른쪽. 즉 일방적인 방향으로 저장되고 읽혀진다. 마치 우리가 책을 읽거나 글을 쓸때 왼쪽에서 오른쪽으로 읽거나 쓰는 것과 같다.

http://www.terms.co.kr 에서 Endian에 대하여 검색하면 다음과 같은 내용을 얻을 수 있다.

-
리틀 엔디안 순서에 대한 논리는, 수의 값을 증가시킬 때 수의 왼편에 자릿수를 추가해야할 필요가 있을지 모른다는 것이다 (지수가 아닌 경우에, 더 큰 숫자는 더 많은 자릿수를 갖는다). 빅 엔디안으로 정렬되어 저장되어 있는 숫자는 두 숫자를 더한 결과를 저장하기 위해 모든 자릿수를 오른쪽으로 옮겨야하는 일이 종종 발생한다. 그러나 리틀 엔디안 방식으로 저장된 숫자에서는, 최소 바이트가 원래 있던 자리에 그대로 머물 수 있으며, 새로운 자리 수는 최대 수가 있는 주소의 오른쪽에 추가될 수 있다. 이것은 일부 컴퓨터 연산들이 매우 단순해지고 빠르게 수행될 수 있다는 것을 의미한다.
-

위에서 수의 값을 증가시킬때 왼편으로 자릿수를 추가한다는 의미는 10진수 일때 50이라는 숫자에서 550으로 바뀔 경우 자리수가 왼쪽으로 늘어난다는 의미이다. 이것을 컴퓨터의 기준으로 볼 때는 바이트가 1개 늘어나기 때문에 메모리의 공간이 더 필요하게 되어 오른쪽에 추가 된다는 것이다.

그리고 www.terms.co.kr 에서는 에릭레이몬드의 말도 인용하고 있다.

-
에릭 레이몬드는 인터넷 도메인 이름과 전자우편 주소들이 리틀 엔디안 방식으로 표현된 것이라고 말한다. 예를 들어 만약, 텀즈 사이트의 주소를 빅 엔디안 방식으로 쓴다면 다음과 같은 형식을 가질 것이다.
kr.co.terms.www
-

에릭레이몬드에 대해 짧게 설명하면, 그는 1970년 후반의 ARPAnet시대부터 인터넷과 해커문화에 매료되어 호기심을 갖고 관찰하고 참여해 온 해커이다. 그의 여러 오픈소스 프로젝트는 모든 주요 리눅스 배포판에 포함되어 있고, 가장 잘 알려진 것은 fetchmail이다. GNU Emacs와 ncurses에도 크게 공헌하였다.(이 내용은 O'Reilly 출판의 OPENSOURCES라는 책을 참고 하였다.)

fetchmail에 대해서 궁금하면 그가 작성한 성당과 시장(The Cathedral and the Bazzar)이라는 제목의 에세이를 읽어보기 바란다.

이것은 두 종류의 오픈소스 개발방법(성당-BSD, 시장-Linux)과 시장방식의 개발방법의 이점, 그리고 여러분의 프로그래밍 방법론에 대해 중요한 도움을 주게 될 것이다. 이 문서에 대해 궁금하면 본인에게 연락할 경우, 문서의 번역본을 제공할 것이다.

추가적인 정보는 다음의 사이트에 방문하면 좀 더 자세한 정보를 얻을 수 있다.

http://www.terms.co.kr/big-endian.htm

댓글 없음:

댓글 쓰기