본문 바로가기

Reverse Engineering/Reversing 이론 설명

[CPU] 8086 세그먼트와 오프셋의 개념

8086 1978 인텔에서 제작된 CPU로서 처음으로 x86 아키텍처를 적용한 제품입니다.
(
모든 80x86 CPU 8086 기초로 하여 만들어졌으므로 8086에서 사용되는 명령어는 다른 80x86 제품에서도 사용할 있습니다.) 클럭은 제품에 따라 4.77MHz에서 10MHz까지 다양하며 16 bit 레지스터를 사용하였습니다. 내부적으로는 16 bit 레지스터를 사용했지만, 어드레스 버스가 20 bit 였으므로 1024 * 1024 = 1048576 (byte) = 1MB 만큼의 메모리를 사용할 있었습니다.

어드레스 버스가 20 bit 였기때문에 최대 1MB(2^20) 메모리까지 사용할 있었지만, 바이오스에서 사용하는 영역인 384KB 제외하면 640KB만을 실제로 사용할 있었습니다.

0x0 - 0x3FF
0x400(1KB) IVT 사용하고, 0x400 - 0x4FF 까지는 BDA, 0x500 - 0x9FFFF 까지는 자유롭게 사용할 있다고 나와있지만 사실 0x7C00 - 0x7DFF 512byte에는 부트코드 있어야합니다. 또한 0x9FC00 - 0x9FFFF 1KB 영역에는EBDA(Extended BIOS Data Area) 있으므로 사용할 없습니다. IVT BDA 그리고, 이런 부분들을 제외하면 640KB 정도가 됩니다. 상위의 0xA0000 - 0xFFFFF 까지의 0x60000(384KB) ROM 영역입니다.

x86
초기모델인 8086 이렇게 1MB(20 bit) 메모리를 사용하도록 설계되어 있었지만, CPU 내부 구조는 16 bit 레지스터를 사용하고 있었으므로 최대 2^16 65536 Byte, 64KB 메모리밖에 사용할 없었습니다. 이에 인텔은 세그먼트 오프셋이라는 개념을 도입해서 16 bit 레지스터를 이용해 20 bit 가리킬 있도록 합니다.

Segment : Offset 같이 쓰며, 이렇게 표시되어있는 논리주소는 세그먼트를 4bit 시프트하고, 거기에 오프셋을 더해 물리주소로 변환합니다. 예를들어 0x0700:0x0C00 이라면 0x0700 4bit 왼쪽으로 시프트(16진수로는 자릿수 0 더해서)하고 거기에 오프셋 값을 더해서 0x7000 + 0x0C00 = 0x7C00 됩니다. 방법을 통해서 0x00000 부터 최대 0xFFFFF 까지 1MB 메모리를 사용할 있게 되었습니다. 따라서 하나의 세그먼트는 64KB 되며, 세그먼트부터 다음 세그먼트 사이에 존재하는 주소에 접근하기 위해서 오프셋을 사용합니다.

CS IP 같이 쓰여 CS : IP 형태로 명령어 인출에 사용됩니다. 스택 처리는 SS : SP 같은 형태로 스택 세그먼트 레지스터와 SP 레지스터가 사용되며 데이터 접근에는 주로 DS 세그먼트 레지스터가 주로 사용됩니다.