MS-DOS 소스 공개 — Microsoft가 GitHub에 올린 진짜 이유와 Claude로 읽는 법

목차

MS-DOS 4.0 소스가 GitHub microsoft/MS-DOS 저장소에 올라온 것은 2024년 4월이다. 라이선스는 MIT. 그 이전 1.25, 2.0 소스는 2014년 Computer History Museum 협력으로 공개된 게 있고, 4.0은 두 번째 큰 공개에 해당한다. 어셈블리 원본과 일부 컴파일 결과물이 같이 들어 있다(출처: Microsoft Open Source Blog, 2024-04).

한편, 이걸 처음 받아본 이유는 단순하다. 옛날 OS가 부팅까지 얼마나 적은 코드로 돌아가는지 궁금했다. 직접 받아보니 어셈블리 지식이 거의 없는 상태에서 Claude를 옆에 두고 읽는 방식이 가장 빨랐다. 빌드는 못 끝냈다. MASM 5.10이라는 16비트 시절 어셈블러가 필요한데 이걸 macOS에서 돌리는 게 생각보다 번거롭다.

이 글은 신입이 "이거 어떻게 시작해요?" 물었을 때 바로 보여줄 수 있게 쓴 가이드다. 받는 법, 구조 보는 법, AI로 읽는 법, 막힌 지점까지 순서대로 정리한다.

공개된 DOS 소스 — 무엇이 어디까지 풀렸나

GitHub 저장소에 두 묶음이 들어 있다. v1.25/v2.0 디렉터리와 v4.0 디렉터리다. 라이선스는 MIT라서 상업적 재배포까지 가능하다는 뜻이 된다(작성 시점 기준).

버전 최초 공개 시점 주요 구성
MS-DOS 1.25 2014년 (CHM 협력) 어셈블리 원본, 일부 문서
MS-DOS 2.0 2014년 (CHM 협력) 어셈블리 원본, 빌드 스크립트
MS-DOS 4.0 2024-04 GitHub 어셈블리 + PASCAL 코드, 바이너리 일부

4.0이 흥미로운 건 IBM과 공동 작업한 멀티태스킹 가지(브랜치)가 포함돼 있다는 점이다. 이 가지는 PC 시장에서 결국 살아남지 못했다. 그래도 1980년대 중반 Microsoft가 멀티태스킹을 어떻게 상상했는지 그대로 남아 있다.

86-DOS 흔적은 어디 있나

원조에 해당하는 Tim Paterson의 86-DOS는 공식 저장소에는 없다. 1.25 코드 안에 흔적이 남아 있어서 Paterson이 설계한 인터럽트 호출 규약(INT 21h)이 그대로 보인다(개인적으로 이게 가장 흥미로웠다). 1.25만 봐도 86-DOS의 골격이 거의 그대로 드러난다고 보면 된다.

왜 공개했나 — 오픈소스화 배경

Microsoft가 갑자기 마음을 바꿔서 푼 건 아니다. 흐름이 있다.

첫째, 회사의 오픈소스 기조 자체가 바뀐 지 오래다. 2014년 사티아 나델라 체제 이후 .NET Core, TypeScript, VS Code, Windows Terminal까지 핵심 프로젝트가 줄줄이 오픈소스로 풀렸다. PowerShell도 마찬가지다. DOS는 그 흐름의 끝자락에 붙은 셈이다.

예를 들어, 둘째, 상업적 위협이 사실상 없다. MS-DOS는 1990년대 후반 이후 새 라이선스가 거의 팔리지 않은 제품이다. 코드를 공개해도 잃을 매출이 없고, 반대로 역사 보존이라는 명분과 개발자 커뮤니티의 호의를 얻는다.

그러나, 셋째, Computer History Museum이라는 매개가 있었다. 1.25/2.0 공개 당시에도 CHM이 보존 파트너로 들어왔다. 4.0 공개 때는 영국 박물관 큐레이터가 옛 디스켓을 발굴하면서 시작됐다고 알려져 있다. 박물관 협력은 라이선스 협상과 명분 확보 모두에 유리한 구조다.

물론, 여기서 짚어둘 게 있다. Microsoft가 "오픈소스 친화 회사"라는 평가를 받는 건 사실이지만, Windows NT 커널이나 Office 코어를 풀 일은 당분간 없다고 보는 게 안전하다. DOS 공개는 "잃을 게 없는 역사적 자산"에 해당한다.

GitHub에서 받아 구조 파악하기

가이드 시작. 신입이 노트북 열고 따라 할 수 있는 순서다.

# 저장소 클론
git clone https://github.com/microsoft/MS-DOS.git
cd MS-DOS

# 디렉터리 구조 확인
ls -la
# v1.25/  v2.0/  v4.0/  README.md  LICENSE

4.0 안으로 들어가면 src 아래에 BIOS, CMD, DOS, MAPPER 같은 폴더가 있다. 핵심 커널 코드는 DOS 디렉터리다. 가장 먼저 열어볼 파일은 다음 세 개로 좁히면 된다.

  • MSDATA.ASM — 시스템 전역 데이터 영역 선언
  • MSINIT.ASM — 부팅 초기화 루틴
  • MSDISP.ASM — INT 21h 시스템 콜 디스패처

이 셋만 훑어도 DOS가 "사실상 INT 21h 점프 테이블 + 파일시스템"이라는 사실이 보인다. UNIX의 시스템 콜 테이블과 구조적으로 닮았다. 같은 시기에 같은 문제를 풀면 비슷한 답에 도달한다는 게 인상적이다.

파일 인코딩 주의

8.3 파일명에 익숙하지 않은 사람은 처음에 헷갈린다. 일부 파일은 CR/LF가 아닌 LF 단독이거나, 탭 크기가 8이 아닌 다른 값으로 정렬돼 있다. VS Code에서 열 때 우측 하단 인코딩을 IBM437로 바꾸면 깨진 박스 문자가 제대로 보인다. 이거 한 번 안 맞춰두면 주석 절반이 글자 깨짐으로 보여서 읽기 어려워진다.

Claude로 어셈블리 코드 읽기

여기가 이 글의 핵심이다. 16비트 x86 어셈블리를 처음 보면 막막한데, AI 도구를 쓰면 입문 비용이 확 떨어진다.

프롬프트 예시:
아래는 MS-DOS 4.0 MSDISP.ASM 일부다.
INT 21h 디스패처 진입 부분으로 보인다.
한 줄씩 무슨 일을 하는지 한국어로 설명해줘.
특히 AH 레지스터로 서비스 번호를 분기하는 흐름을 강조해줘.

[코드 100~200줄 붙여넣기]

Claude한테 이런 식으로 물으면 라인별 주석과 흐름 요약을 한 번에 받는다. 8086 명령어 의미, 세그먼트:오프셋 주소 지정 방식, 호출 규약(CALL FAR, RETF)까지 같이 설명해준다.

게다가, Cursor를 쓰면 더 편한 편이다. 저장소를 통째로 열어두고 특정 함수에서 Ctrl+L로 채팅을 띄우면 컨텍스트가 자동으로 잡힌다. 다만 Cursor 기본 모델로는 16비트 어셈블리 해석이 가끔 부정확하다. 모델을 Claude Sonnet 계열로 바꿔두는 게 체감상 정확도가 높다.

결국, API로 자동화하고 싶다면 이런 식으로 짠다.

import anthropic
from pathlib import Path

client = anthropic.Anthropic()

# 어셈블리 파일을 청크 단위로 요약
asm_text = Path("v4.0/src/DOS/MSDISP.ASM").read_text(encoding="cp437")

# 너무 길면 잘라서 보낸다 (토큰 한도 고려)
chunk = asm_text[:8000]

resp = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=2000,
    messages=[{
        "role": "user",
        "content": (
            "다음은 MS-DOS 4.0 어셈블리 소스의 일부다. "
            "주요 함수, 레지스터 사용 규칙, INT 21h 서비스 번호를 "
            "표로 정리해줘.\n\n" + chunk
        )
    }]
)

print(resp.content[0].text)

즉, 이걸 디렉터리 전체에 돌리면 함수별 요약 노트가 자동으로 만들어진다(개인 학습 용도). 핵심은 "AI가 어셈블리 입문 부담을 흡수해준다"는 점이다.

프롬프트 한 가지 팁

"이 코드가 무엇을 하는지 설명해줘"는 약한 질문이다. 차라리 이렇게 묻는 게 출력 품질이 좋다.

  • "이 함수에 진입할 때 AX, BX, CX, DX에 어떤 값이 들어 있다고 가정하나?"
  • "이 코드의 호출자는 어떤 INT 21h 서비스를 부른 사용자인가?"
  • "현대 C 코드로 의사 변환해줘."

특히, 세 번째가 특히 유용하다. 어셈블리 200줄이 C로는 30줄로 줄어드는 경우가 많아서 의도 파악이 빠르다.

직접 빌드해보려다 막힌 지점

또한, 여기서부터는 시행착오 기록이다.

특히, MS-DOS 4.0을 실제로 빌드하려면 MASM(Microsoft Macro Assembler) 5.10이 필요하다. 1989년경 나온 16비트 어셈블러다. 이걸 어떻게 구하는지부터 막힌다.

# DOSBox 안에서 실행한다고 가정
mount c ./build
c:
cd MSDOS40
masm /Mx MSDISP.ASM, MSDISP.OBJ
# 출력 예시
# Microsoft (R) Macro Assembler Version 5.10
# Assembling: MSDISP.ASM

게다가, macOS 위에서 DOSBox를 띄우고, 그 안에 MASM을 올린 다음, 클론한 소스를 마운트해서 빌드하는 식으로 가야 한다. 실제로 해보면 경로 길이 제한(8.3 파일명) 때문에 일부 헤더가 안 잡히고, LINK.EXE가 못 찾는 라이브러리 경고가 떠서 한참 헤맸다. 결국 부팅 가능한 디스크 이미지 생성까지는 못 갔다.

특히, GitHub 저장소 README 기준으로 빌드 가이드가 첨부돼 있긴 하다. 환경 차이가 커서 그대로 따라가도 막히는 경우가 흔하다. 빌드가 목적이라면 잘 정비된 PCem이나 86Box 같은 에뮬레이터 위에 MS-DOS 5.0을 깔고 그 안에서 빌드하는 쪽이 더 안정적이라는 평가가 많다.

신입한테 권하는 학습 순서

그런데, 이 코드를 처음 보는 사람한테 권하는 진입 순서다. 회사에서 신입이 물어보면 이걸 그대로 보내준다.

  1. git clone만 받아두기. 빌드는 일단 잊는다.
  2. v2.0 안의 짧은 파일부터 연다. 4.0보다 2.0이 훨씬 짧고 읽기 쉽다.
  3. Claude나 Cursor를 옆에 띄워두고 한 파일씩 "이 파일의 목적과 주요 진입점은?" 형태로 묻는다.
  4. INT 21h 서비스 번호 표를 한 장 출력해서 옆에 둔다(Ralf Brown’s Interrupt List가 사실상 표준이다).
  5. 의사 C 코드로 변환된 결과만 노트에 정리한다. 원본 어셈블리를 외울 필요는 없다.
  6. 부팅 흐름이 잡히면 그제서야 빌드/에뮬레이터로 넘어간다.

순서를 지키지 않으면 환경 구성에서 며칠을 날린다. 환경부터 만지면 코드를 못 본다.

주의사항과 한계

라이선스가 MIT라고 해서 4.0 코드를 잘라 현대 프로젝트에 그대로 붙이는 건 의미가 없다. 16비트 실모드 가정, 8.3 파일명, 단일 프로세스 모델 위에 짜인 코드라서 64비트 리눅스 위에서 쓸 부분이 사실상 없다. 학습용, 보존용, 아카이브용으로 보는 게 맞다.

즉, 공개된 코드는 "최종 릴리스 버전의 일부"이지 "개발 과정 전체"가 아니라는 점도 중요하다. 중간 브랜치, 리뷰 코멘트, 빌드 로그, 테스트 케이스 같은 컨텍스트는 빠져 있다. 코드만 보고 "왜 이렇게 짰는지"를 추측할 수밖에 없는 구간이 많다.

실제로, AI로 어셈블리를 읽는 방식 자체에도 한계가 있다. Claude가 가끔 8086에는 없는 명령어를 있는 것처럼 설명하거나, 보호 모드 개념을 실모드 코드에 섞어 설명하는 경우를 봤다. 결과를 그대로 믿지 말고 Intel 8086 매뉴얼 PDF를 한 권 옆에 두는 편이 안전하다.

다만 이 코드가 GitHub에 살아 있는 한 OS의 진입 지점을 직접 읽어볼 수 있다는 사실 자체는 큰 자산이다. 그 가치가 학습용을 넘어 어디까지 확장될지는 더 지켜봐야 한다.

관련 글