EXE 檔案結構、載入時重定位、覆蓋機制、堆疊初始化與常駐程式設計,是組合語言系統程式設計師必須掌握的核心知識。本文透過三個原始檔(a1.asm/a2.asm/a3.asm)連結實驗、root3.exe 靜態覆蓋展示、ovlayer/ovlayee 動態覆蓋調度、t.asm 堆疊初始化追蹤,完整解析 DOS EXE 機制。
GROUP / SEGMENT 定義組與段BYTE/WORD/PARA/PAGE,預設 PARA)、結合(PUBLIC 尾接、COMMON 共基址)、類別('CLASS',同類相鄰)| 邏輯段 | 類別 | 來源 | 備註 |
|---|---|---|---|
| SEG1 | 匿名 | a1 | 單邏輯段 |
| TOUCH | 匿名 | a1+a3 | PUBLIC 結合,程式碼相接 |
| STK1 | 匿名 | a1 | STACK 類型 |
| SEG2 | 匿名 | a3 | 單邏輯段 |
| SEG1 | 匿名 | a3 | 同名不同類 → 獨立邏輯段 |
| OVLAP | DEC_ | a1+a2 | COMMON 結合,a2 覆寫 a1 資料 |
| SEG3 | DEC_ | a2 | 單邏輯段 |
| STK2 | _STK | a2+a3 | STACK 類型,PUBLIC 結合空間相鄰 |
00h: 'MZ' 簽名 (4D 5A)
02h: 檔案長度模 512 餘數
04h: 檔案長度除 512 商
06h: 重定位表項數
08h: 前部佔用段落數 (段落=16位元組)
0Ah: 最小額外段落需求
0Ch: 最大額外段落需求
0Eh: SS 相對載入模組首段落數
10h: SP 初值
12h: 檢查和
14h: IP 初值
16h: CS 相對載入模組首段落數
18h: 重定位表檔案偏移
1Ah: 覆蓋號
每項 4 位元組:W_O (檔案內偏移低字)、W_P (段落號)。執行時位址 = (W_P << 4) + W_O + 載入段值。
COMMAND.COM 尋找空閒記憶體區塊 (MCB),建立 PSP (10h 段落)。載入段值 = PSP段落 + 10h)。CS/SS + 載入段值 → 執行 CS:IP/SS:SP。重定位因子(通常 = 載入段值)→ 修正載入模組內段值指令。-d 100 l 2e ; 顯示載入頭
-d 11e l 8 ; 顯示重定位表 (4項)
-u 321 ; 反組譯碼區,觀察修正後段值
link4 root (ov_near ov_far) (ov_far1), root3, 3, , ,
root.obj → 常駐區塊 (Overlay 0)(ov_near ov_far) → Overlay 1(ov_far1) → Overlay 2OVERLAY_DATA:覆蓋表(含覆蓋數、CS 段落號、檔名等)OVERLAY_AREA / OVERLAY_END:載入區域標記OVERLAY_DATA 內部偏移CS:IP 入口)。INT 21h AH=4Ah 釋放尾部記憶體。載入段值 (MCB 高端+1)、重定位因子 (自訂,如段名 s1/s2 所在段)。INT 21h AH=4B03h 載入覆蓋模組(不建立 PSP,直接映射)。CALL DWORD PTR entry 執行覆蓋模組。RETF 返回。重定位因子 重複載入同一覆蓋檔,因段值不同而顯示不同資料。work,故所有段值暫定為 0,重定位後 = 重定位因子。END @,CS:IP=0,借用調度器堆疊。MOV AX, work / MOV DS, AX 利用重定位後的段值定址資料。.STARTUP 展開碼mov ax, 2572h ; AH=25h (設定中斷向量), AL=72h (向量號)
lea dx, i72 ; 自訂 ISR 位址
int 21h ; 安裝 INT 72h
mov dx, 256 + i27 ; 計算 PSP 常駐段落數
mov byte ptr es:[1], 27h ; 標記 PSP
sub i27[2], 16 ; 調整段值指向 PSP
call dword ptr i27 ; 轉入 PSP:0 (模擬程式結束返回 DOS)
; 初始化前
DS=188B SS=189D SP=0020 (SS 指向載入模組後堆疊段, SP=EXE頭預設 20h)
; 初始化後
DS=189B SS=189B SP=0040 (DS/SS 統一指向 @data, SP 增加堆疊大小 20h)
.STARTUP 實際執行:CLI → MOV SS,DX → SHL BX,4 → ADD SP,BX → STI,將堆疊從載入模組末端移至資料段高端,並擴大堆疊空間。
EXE 檔案機制涵蓋:段組類邏輯→連結器排列→載入頭與重定位表→執行時重定位→靜態覆蓋 (Link4 括號) →動態覆蓋 (4B03h) →堆疊初始化 (.STARTUP)。掌握這些細節,才能編寫高效常駐程式、覆蓋大型應用、精確控制記憶體佈局,是 DOS 系統程式設計的終極內功。