2026년 10월 12일 월요일

21세기 DOS 프로그래밍 #3 - DOS2 뱅킹

디스크롬의 뱅킹을 얘기하려는 것은 아니구요.

확장 BIOS로 지원되는 메모리매퍼의 뱅킹 이야기입니다~


메모리매퍼 세그먼트는 16KB입니다.

저의 프로그램에서 원하는 뱅킹은 Page 0,1의 32KB 영역입니다.


프로그래밍을 안해보셨으면 text, data, bss 등의 단어가 생소하실 수도 있는데요.

대충 보고 넘어가셔도 괜찮습니다요 ㅎ.ㅎ


메모리맵은 이런식으로 구성됩니다.

0000H ~ 00FFH = DOS2 Zero page

0100H ~ 7FFFH = text + data + bss + local heap

8000H ~ 93FFH = Mapper table, Banking stack, ISR 등의 Helper area

9400H ~ FFFFH = global var. + global bss + global heap + WORKAREA


전역변수(global var.)는 MAP파일에서는 comm으로 표시됩니다.

여러 뱅크에서 공통으로 접근하는 변수들을 쓸 때 필요합니다.


뱅킹 영역(0000H ~ 7FFFH)은 시스템 메모리매퍼 세그먼트 2개를 묶어서 사용합니다.

메모리매퍼 최대용량(4080KB)에서 127개의 뱅크를 사용할 수 있습니다.


프로그램 내에서 사용되는 뱅크번호는 논리(logical) 세그먼트가 되겠구요.

프로그램 로더는 필요한 용량만큼 실제 세그먼트를 할당 받아서 논리 뱅크와 연결합니다.

로더는 뱅크 0번으로 고정되고 실행파일(*.COM)으로 빌드됩니다.

나머지 뱅크들은 빌드 후 하나의 파일(*.OVL)로 묶여집니다.


malloc() 등의 heap을 사용하는 경우는 뱅킹 영역의 local heap이 사용됩니다.

bl_malloc() 등의 함수를 쓰면 global heap을 할당 받을 수 있습니다.

여러 뱅크에서 전역으로 접근이 필요한 경우에 쓰면 됩니다.


유저 ISR 루틴도 뱅킹이 지원됩니다.

따라서 외부 인터럽트, VDP H-Blank, V-Blank 등의 루틴을 여러 뱅크에 나눠 놓을 수 있어요.


뱅킹과 상관없이 매퍼 세그먼트를 이용하여, 대용량의 메모리를 할당할 수 있습니다.

bl_lmem_alloc() 등의 함수로 이루어져있습니다.

큰 데이터를 한번에 로딩할 때 쓰면 되겠습니다. (예: IMS 플레이어 등)


그 외,

시스템의 세그먼트가 부족한 경우는 특정 뱅크를 동적으로 로딩할 수도 있습니다.

설계 초기에는 디스크의 스왑파일(*.SWP)로 가상 메모리를 쓰는 것도 고려했는데,

거북이 MSX를 달팽이 속도로 만들 이유는 없어서, 가상 메모리는 제외되었어요 ㅎ.ㅎ


HI-TECH C 자체는 일반 CP/M의 TPA(64KB) 영역만 쓰는 프로그램만 컴파일이 가능합니다.

이걸 소스 파일을 뱅크로 나눠서 빌드 후 뱅킹 함수로 연결 하거나,

전역 변수를 처리 등의 부가 작업은 별도의 툴을 제작해서 썼습니다.


전체 툴체인은 로컬 git으로만 작업 후 릴리스 파일만 파라동 자료실에 올렸었는데요.

나중에는 귀찮아서 github에 그대로 올려버렸습니다. 흐...

아마 살짝 써보신 분들도 계실 듯요. 아래 링크는 참고만 하셔요 ㅎ.ㅎ

https://github.com/sharksym/CPMEMU_HI-TECH_C


그럼, 다음 편에서 이어집니다요~