首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

組合語言 EXE 檔案深度解析:重定位、覆蓋、堆疊初始化與常駐程式架構

     編輯:組合語言

前言

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',同類相鄰)
  • 邏輯段 = 組合邏輯段(多源檔同名同類同屬性合併)或單邏輯段

三源檔連結實驗 (a1+a2+a3 → a.exe)

邏輯段類別來源備註
SEG1匿名a1單邏輯段
TOUCH匿名a1+a3PUBLIC 結合,程式碼相接
STK1匿名a1STACK 類型
SEG2匿名a3單邏輯段
SEG1匿名a3同名不同類 → 獨立邏輯段
OVLAPDEC_a1+a2COMMON 結合,a2 覆寫 a1 資料
SEG3DEC_a2單邏輯段
STK2_STKa2+a3STACK 類型,PUBLIC 結合空間相鄰

排列準則

  1. 依連結順序(命令列檔案順序)
  2. 同檔內依段定義順序
  3. 同類別依類名大寫 ASCII 排序

第二部分:EXE 載入頭、重定位表與執行時重定位

EXE 兩部結構

  • 前部:載入頭(28h 位元組)+ 重定位表
  • 後部:載入模組(映像體)

載入頭關鍵欄位 (偏移 00h)

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 + 載入段值。

執行時重定位流程

  1. COMMAND.COM 尋找空閒記憶體區塊 (MCB),建立 PSP (10h 段落)。
  2. 載入模組置於 PSP 之後(載入段值 = PSP段落 + 10h)。
  3. 載入頭中 CS/SS + 載入段值 → 執行 CS:IP/SS:SP。
  4. 重定位表每項 + 重定位因子(通常 = 載入段值)→ 修正載入模組內段值指令。

DEBUG 驗證範例 (a.exe)

-d 100 l 2e   ; 顯示載入頭
-d 11e l 8    ; 顯示重定位表 (4項)
-u 321        ; 反組譯碼區,觀察修正後段值

第三部分:靜態覆蓋 — Link4 括號語法

連結命令

link4 root (ov_near ov_far) (ov_far1), root3, 3, , ,
  • 未括號 root.obj → 常駐區塊 (Overlay 0)
  • (ov_near ov_far) → Overlay 1
  • (ov_far1) → Overlay 2

產生區塊

  • OVERLAY_DATA:覆蓋表(含覆蓋數、CS 段落號、檔名等)
  • OVERLAY_AREA / OVERLAY_END:載入區域標記

重定位表新增項目

  • 遠呼叫/遠跳轉目標段值(需運行時由覆蓋管理器修正)
  • OVERLAY_DATA 內部偏移

第四部分:動態覆蓋 — 功能 4B03h 調度

常駐調度器 (ovlayer.exe)

  1. 讀取覆蓋模組 EXE 載入頭(取得 CS:IP 入口)。
  2. INT 21h AH=4Ah 釋放尾部記憶體。
  3. 準備參數塊:載入段值 (MCB 高端+1)、重定位因子 (自訂,如段名 s1/s2 所在段)。
  4. INT 21h AH=4B03h 載入覆蓋模組(不建立 PSP,直接映射)。
  5. CALL DWORD PTR entry 執行覆蓋模組。
  6. 覆蓋模組 RETF 返回。
  7. 切換 重定位因子 重複載入同一覆蓋檔,因段值不同而顯示不同資料。

覆蓋模組 (ovlayee.exe) 關鍵設計

  • 僅含單一邏輯段 work,故所有段值暫定為 0,重定位後 = 重定位因子。
  • 無 END @,CS:IP=0,借用調度器堆疊。
  • MOV AX, work / MOV DS, AX 利用重定位後的段值定址資料。

第五部分:堆疊初始化 (.STARTUP) 微操作追蹤

MASM 6.11 .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)

DEBUG 觀察堆疊遷移

; 初始化前
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 系統程式設計的終極內功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved