레지스터(Register)의 이해
리버스 엔지니어링(Reverse Engineering)을 하는데 있어 여러 가지 지식이 많이 필요한데, 그 중 하나가 바로 레지스터(Register)이다.
레지스터는 CPU(Central Processing Unit)가 요청을 처리하는 데 필요한 데이터를 일시적으로 저장하는 기억장치이다.
실제로 컴퓨터에서 데이터를 영구적으로 저장하기 위해서는 하드디스크를 이용해야 하고,
임시적으로 저장하는 장소를 메모리(RAM)이라고 알고 있을 것이다.
하지만 메모리로 연산의 결과를 보내고 영구적으로 저장할 데이터를 하드디스크에 저장해야 하는 등의
명령을 처리하기 위해서는 이들에 대한 주소와 명령의 종류를 저장할 수 있는 기억 공간이 하나 더 필요하다.
그리고 이 공간은 무리 없이 명령을 수행하기 위해 메모리보다 빨라야 한다.
바로 이런 역할들을 하는 것이 CPU옆에 붙어있는 레지스터이다.
레지스터는 공간은 작지만 CPU와 직접 연결되어 있으므로 연산 속도가 메모리보다 실제 수십 배에서 수백 배까지 빠르다.
그리고 CPU는 자체적으로 데이터를 저장할 방법이 없기 때문에 메모리로 직접 데이터를 전송할 수 없다.
때문에 연산을 위해서는 반드시 레지스터를 거쳐야 하며, 이를 위해서 레지스터는 특정 주소를 가리키거나 값을 읽어올 수 있다.
32비트(Bit)? 64비트(Bit)?
요즈음 컴퓨터들은 일반적으로 32비트/64비트 시스템을 많이 사용한다.
여기서 말하는 비트 수는 명령을 한 번에 처리할 수 있는 레지스터의 비트 수인데,
쉽게 말해 하나의 레지스터가 저장 가능한 공간의 크기가 32비트인지 64비트인지를 나타내는거라 보면 된다.
(32비트 시스템이 인식 가능한 메모리가 4GB인 이유가 이와 같은데, 32비트로 한 번에 표현할 수 있는 주소가 4GB이기 때문이다.
물론 이는 다른 알고리즘을 사용하면 더 인식할 수도 있다. 하지만 이는 여러 가지 문제가 있다.)
예전의 16비트 컴퓨터는 느리고 항상 불안정했었다.
항상 16비트로 데이터를 처리하기 때문이었는데, 16비트가 표현할 수 있는 주소 공간은 매우 협소했었다.
그런데 계속적으로 멀티미디어가 발전하고, 컴퓨터 시스템의 사용자가 늘어남에 따라
프로그램의 용량은 커져야 했고 더욱 많은 메모리 공간을 필요로 했다.
메모리 공간을 아끼기 위해서는 모두 같은 메모리 공간에서 프로그램을 실행시켜야 했고, 프로그램 간의 메모리 침범은 매우 빈번했다.
그리고 프로그램 개발자들은 이를 방지하기 위해 메모리에 대해서 매우 많은 공부를 해야 했다.
이러던 와중에 나올 것이 바로 인텔(Intel)사에서 발표한 80386이다.
물론 이후로도 프로세서가 많았지만, 대부분 속도나 다른 부분에서의 성능 향상이었다.
이 80386이 대단한 이유는 지금도 32비트 프로세서는 80386의 아키텍처(Architecture)를 그대로 사용하고 있다.
이런 32비트 프로세서는 16비트 시스템 용량 부족의 숨통을 완전히 트이게 했다.
그도 그럴 것이 주소 공간을 비교해본다면 16비트(65535)와 32비트(4294967295)의 공간 차이는 어마어마했기 때문이다.
하지만 이런 대단한 발견에도 부족하고 빅데이터라던지,
데이터 사용률의 증가라는 핑계로 또 현대의 컴퓨터는 용량의 부족이라는 한계에 대면하고 있다.
그래서 나온 것이 64비트 체제인데 네트워크 주소에서의 IPv4와 IPv6를 생각하면 이해가 쉽다.
16비트에서의 문제점을 해결한 32비트 시스템, 그리고 이 32비트 시스템의 용량 문제를 해결한 64비트 시스템.
이 중에서 아직까지는 이 32비트가 현대 시스템의 가장 중심 측이고, 리버스엔지니어링에 있어서도 32비트 분석이 주류를 이루고 있다.
64비트 시스템 역시 32비트 시스템의 용량을 확장했을 뿐이므로 32비트 시스템을 잘 이해해야 64비트 시스템도 쉽게 이해할 수 있다.
데이터의 단위
최초 16비트 시스템에서는 0~15비트까지 레지스터 공간을 제공했었다.
여기서 레지스터는 CPU당 한개만 존재하는 것이 아니며, 필요와 용도에 따라 여러 종류가 있었으며,
각 레지스터의 사용 방식에 따라 이름을 구분하여 사용했다.
이런 구조는 32비트로 환경이 변화했을 때도 그대로 유지되었으며(하위 호환을 위해서),
확장의 의미로 각 레지스터의 이름 앞에 E(Extension)을 붙여서 사용하고 있다.
이런 레지스터들에 대해 소개하기 이전에 우선 데이터의 단위를 먼저 보고 넘어가고자 한다.
레지스터 뿐만 아니라 어셈블리어로 시스템의 내부적인 구성을 볼 때 이 단위대로 데이터를 잘 해석해야 하기 때문이다.
① 비트(Bit)
컴퓨터 시스템이 데이터를 연산하고나 표현할 수 있는 제일 기본 단위로, 자리값 마다 0과 1 두가지. 2진수만 표현할 수 있다.
8Bit 00000010은 10진수 2와 같다. 즉 컴퓨터 시스템은 이런식으로 데이터를 이해하고 있다.
② 바이트(Byte)
8개의 비트를 모아서 하나의 바이트(Byte)라 한다. 10진수 0~255까지, 16진수로 0~0xFF까지 표현이 가능하다.
레지스터에서 8비트에 대응되는 레지스터는 AL, AH, BL, BH, CL, CH, DL, DH가 있다.
C언어의 char형, BOOL형 데이터 타입이라고 보면 된다.
③ 워드(Word)
2개의 바이트를 하나로 표현하면 워드(Word)라 하며, 총 16비트이다.
표현할 수 있는 최대값은 10진수 0~65535, 16진수 0xFFFF이며 16비트 레지스터로는 AX, BX, CX, DX, SI, DI, BP, SP, IP가 있다.
하나의 작업 단위라는 뜻으로 많이 사용되며 32비트 시스템에 넘어와서는 워드 단위 자체로 사용되는 비중은 많이 줄었다.
④ 더블워드(DWORD : Double WORD)
워드 2개를 하나로 표현하여 더블워드(DWORD)라 하며, 32비트 표현 단위이다.
10진수 0~4294967295, 16진수 0xFFFFFFFF를 표현할 수 있으며, 레지스터로는 EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP가 있다.
32비트 이후 시스템 부터는 주소 표현(포인터), 기본 정수 단위로 가장 많이 사용된다.
⑤ 킬로바이트(KB : KILOBYTE)
일반 물리적 단위로 ‘킬로‘가 붙으면 1000을 표현하지만
컴퓨터 시스템에서는 기본 2의 제곱으로 값이 표현되어야 하기에 1024바이트를 가리킨다.(32*32바이트)
파일의 단위로 많이 사용되므로 참고만 하자.
⑥ 메가바이트(MB : MEGABYTE)
킬로바이트의 제곱으로 표현한다.(1024*1024바이트 = 1,048,578바이트)
이 역시 파일의 단위로 많이 사용된다.
위 그림은 각 레지스터 별 비트의 크기를 나타냈다.
여기서 AL, AH, AX, EAX가 모두 다른 레지스터로 이해하는 경우가 있는데,
32비트 레지스터 EAX중 16비트를 AX로 접근이 가능하고, AX의 상위 8비트를 AH, 하위 8비트를 AL로 나타낸다.
즉 EAX레지스터가 AX를 포함하고, 이 AX가 AL, AH를 포함하고 있는 형태이다.
이는 16비트 시스템 호환을 위한 설계이기도 하고, 레지스터 공간의 낭비를 없애기 위함이기도 하며,
효율적인 알고리즘을 위한 설계이기도 하다.
'PC리버싱 > (구)기초' 카테고리의 다른 글
리버싱 도구들에관하여 개인적인생각 (0) | 2020.03.14 |
---|---|
리버싱관련자료들(참고용) (0) | 2020.03.14 |
더쉽게배워보자 레지스터에대하여 (0) | 2020.03.14 |
초보자를위한 리버싱 간단요약1 (0) | 2020.03.14 |
생초보자를 위한 리버싱 기초잡이2미완성 (0) | 2020.03.10 |