기타 Lobsters · 2일 전

"그 시절엔 640KB도 넓었다?" DOS가 1MB 메모리를 쥐어짜던 눈물겨운 꼼수들

핵심 요약
  • 인텔 8086과 MS-DOS 시절 레지스터(16비트) 한계 속에서 20비트(1MB) 주소 공간을 쓰기 위해 세그먼테이션 기법이 도입되었습니다.
  • 전체 1MB 중 640KB는 응용프로그램용 기본 메모리로, 상위 384KB는 BIOS와 하드웨어용 상위 메모리 영역(UMA)으로 나뉘어 쓰였습니다.
  • 훗날 상위 CPU가 나왔음에도 DOS 구조상 보호 모드를 온전히 쓰지 못하고 온갖 변칙 기술로 메모리 부족을 버텨야 했습니다.
요약 초기 PC 시대를 풍미했던 인텔 8086 프로세서와 MS-DOS 환경에서 메모리를 어떻게 관리했는지를 다룬 기술 회고 글이 개발자 커뮤니티에서 주목받았습니다. 글쓴이는 레트로 DOS용 GCC 포팅 프로젝트인 DJGPP 관련 글을 준비하다가, 당시 DOS가 처했던 혹독한 메모리 제약과 이를 극복하기 위해 동원된 기법들을 먼저 설명하기 위해 이 글을 작성했다고 밝혔습니다. 1980년대 등장한 인텔 8086 CPU는 20비트 주소 버스를 갖추고 있어 최대 1MB의 메모리만 주소로 지정할 수 있었습니다. 그러나 내부 레지스터는 16비트에 불과해 표현 가능한 값이 64KB(2^16)뿐이었고, 이를 해결하기 위해 '세그먼트(Segment)'와 '오프셋(Offset)'이라는 두 개의 16비트 값을 조합해 20비트 주소를 만들어내는 세그먼테이션(Segmentation) 방식을 채택했습니다. 세그먼트끼리는 서로 겹치며 16바이트 단위로 이동하는 구조였고, 1MB를 초과하는 주소는 21번째 비트를 무시하고 0으로 돌아가는 랩어라운드(Wrap around) 특성을 보였습니다. 이 시절에는 별도의 메모리 관리 장치(MMU)가 없어 널 포인터 참조 같은 오류가 나도 시스템이 즉각 크래시를 내지 않고 엉뚱한 메모리에 접근하는 '리얼 모드(Real mode)'로 동작했습니다. 또한 당시 IBM PC는 1MB 주소 공간을 임의로 두 영역으로 분할했습니다. 첫 640KB는 일반 응용프로그램이 사용할 수 있는 램(RAM) 영역인 '기본 메모리(Conventional Memory)'로 배정했고, 상위 384KB는 BIOS ROM이나 그래픽 카드의 프레임버퍼 등 하드웨어 장치를 메모리 맵 방식으로 노출하는 '상위 메모리(UMA, Upper Memory Area)'로 예약했습니다. 훗날 80286과 80386 CPU가 등장하고 보호 모드(Protected mode)가 지원되었음에도, 레거시 DOS 자체는 보호 모드의 장점을 직접 활용하지 못한 채 온갖 꼼수와 우회책으로 메모리 부족 문제를 틀어막아야 했던 역사적 배경을 흥미롭게 풀어내고 있습니다.
Sponsored · 광고