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

FXN4BH:DOS EXEC 功能 (INT 21h, 4Bh) 載入並執行外部程式示範

     編輯:組合語言

前言:程式載入器的核心 — DOS EXEC 系統呼叫

DOS 2.0 引入 INT 21h, AH=4Bh (EXEC) 功能,允許程式載入並執行另一個程式 (`.EXE` 或 `.COM`),並可選擇載入後返回 (AL=03h) 或覆蓋當前程式 (AL=00h)。FXN4BH.ASM (Ray Duncan, 1983) 示範一個「載入器」:釋放多餘記憶體、準備參數區塊、呼叫 EXEC 載入 CHKDSK.COM、執行完畢後恢復堆疊並繼續執行、最後退出 DOS。程式完整展示了記憶體管理 (4Ah)、環境區塊建立、參數區塊結構、堆疊保存/恢復、錯誤處理等載入器核心技術。

程式流程

  1. 保存返回地址:PUSH DS / XOR AX,AX / PUSH AX 在堆疊建立遠端返回地址 (PSP:0),執行結束後 `RET` 直接回 DOS。
  2. 保存堆疊指標:MOV CS:STK_SEG, SS / MOV CS:STK_PTR, SP 存入程式碼段變數 (常駐於 CS),因 EXEC 會重置 SS:SP。
  3. 釋放記憶體:MOV BX, 100h / MOV AH, 4Ah / INT 21h 保留 100h 段落 (256KB? 實際 100h 段落 = 64KB) 給載入器,其餘歸還系統供子程式使用。
  4. 準備參數區塊 (PAR_BLK):
    • 環境區段 (ENVIR 段值)
    • 命令列緩衝區位址 (CMD_LINE: 長度+內容+CR+0)
    • FCB1 位址 (FCB1)
    • FCB2 位址 (FCB2)
  5. 呼叫 EXEC:MOV DX, PGM_NAME / MOV BX, PAR_BLK / MOV AL, 0 / MOV AH, 4Bh / INT 21h 載入並執行 CHKDSK.COM。
  6. 恢復堆疊與資料段:MOV SS, CS:STK_SEG / MOV SP, CS:STK_PTR / MOV AX, SEG DATA / MOV DS, AX。
  7. 列印成功訊息並退出。

關鍵資料結構

1. 參數區塊

par_blk dw ENVIR           ; 環境區段
 dw offset CMD_LINE        ; 命令列緩衝區偏移
 dw seg CMD_LINE           ; 命令列緩衝區段值
 dw offset FCB1            ; FCB1 偏移
 dw seg FCB1               ; FCB1 段值
 dw offset FCB2            ; FCB2 偏移
 dw seg FCB2               ; FCB2 段值

子程式 PSP:80h 將接收 CMD_LINE 內容,PSP:5Ch/6Ch 接收 FCB1/FCB2 內容。

2. 環境區塊 (ENVIR 段)

envir segment para 'ENVIR'
 db 'PATH=',0
 db 'COMSPEC=A:COMMAND.COM',0
 db 0                      ; 雙重 0 結束
envir ends

子程式繼承此環境區。`COMSPEC` 指定命令解釋器位置,`PATH` 指定可執行檔搜尋路徑。

3. 命令列緩衝區

cmd_line db 4, ' *.*', 0Dh, 0

第一位元組 = 長度 (4),後接參數字串 `*.*`,以 CR (0Dh) 結尾,再補 0。長度不含 CR/0。

4. FCB 範本

fcb1 db 0, 11 dup ('?'), 25 dup (0)   ; 驅動器 0 (預設), 檔名 "???????????"
fcb2 db 0, 11 dup (' '), 25 dup (0)   ; 驅動器 0, 檔名空白

記憶體管理關鍵點

  • 載入器編譯為 `.EXE` (非 `.COM`),擁有獨立區段 (CODE, DATA, STACK, ENVIR)。
  • INT 21h, AH=4Ah (修改配置區大小) 必須在 EXEC 前呼叫,否則子程式無可用記憶體。
  • EXEC 成功後,子程式佔用釋放的記憶體,載入器堆疊/資料段被暫時覆蓋。返回時必須從 CS 變數恢復 SS:SP/DS。
  • 若 EXEC 失敗 (CF=1),錯誤碼在 AX (1=記憶體不足, 2=檔案不存在...),載入器應處理錯誤而非直接退出。

完整原始碼

name FXN4BH
page 55,132
title 'FXN4BH --- demo PC-DOS EXEC function'
cr equ 0dh
lf equ 0ah
cseg segment para public 'CODE'
assume cs:cseg,ds:data,ss:stack
demo proc far
push ds
xor ax,ax
push ax
mov cs:STK_SEG,ss
mov cs:STK_PTR,sp
mov bx,100h
mov ah,4ah
int 21h
jc ALLOC_ERR
mov ax,seg DATA
mov ds,ax
mov es,ax
mov dx,offset MSG2
mov ah,9
int 21h
mov dx,offset PGM_NAME
mov bx,offset PAR_BLK
mov al,0
mov ah,4bh
int 21h
mov ss,cs:STK_SEG
mov sp,cs:STK_PTR
mov ax,seg DATA
mov ds,ax
mov dx,offset MSG3
mov ah,9
int 21h
ret
alloc_err:
mov dx,offset MSG1
mov ah,9
int 21h
ret
demo endp
stk_seg dw 0
stk_ptr dw 0
cseg ends
stack segment para stack 'STACK'
db 64 dup (?)\n />stack ends
data segment para public 'DATA'
msg1 db cr,lf,'Unable to release memory.',cr,lf,'$'
msg2 db cr,lf,'Memory above loader released.',cr,lf,'Now loading CHKDSK.COM.',cr,lf,'$'
msg3 db cr,lf,'Loader regained control from CHKDSK,',cr,lf,'now making final exit to PC-DOS.',cr,lf,'$'
pgm_name db 'CHKDSK.COM',0
par_blk dw ENVIR
dw offset CMD_LINE
dw seg CMD_LINE
dw offset FCB1
dw seg FCB1
dw offset FCB2
dw seg FCB2
cmd_line db 4,' *.*',cr,0
fcb1 db 0, 11 dup ('?'), 25 dup (0)\n />fcb2 db 0, 11 dup (' '), 25 dup (0)\n />data ends
envir segment para 'ENVIR'
db 'PATH=',0
db 'COMSPEC=A:COMMAND.COM',0
db 0\n />envir ends\n />end demo

教學價值與現代映照

  • EXEC 參數區塊結構:環境區段、命令列、FCB1/2 位址 — 現代 Windows `CreateProcess` `lpEnvironment`、`lpCommandLine`、`STARTUPINFO` 等參數的直接祖先。
  • 記憶體釋放與子程式共享:載入器主動縮小自身佔用 (4Ah),騰出空間給子程式 — 現代行程建立時 OS 自動管理虛擬記憶體,但嵌入式/裸機系統仍需手工管理記憶體區塊。
  • 堆疊保存/恢復:EXEC 會重置 SS:SP,載入器必須在 CS/靜態變數中保存原堆疊指標 — 現代執行緒/協程切換同樣需保存堆疊指標 (SP/ESP/RSP)。
  • 環境區塊繼承:子程式自動複製父程式環境區 — 現代 `CreateProcess` `bInheritHandles` / 環境區塊指標同樣控制繼承行為。
  • 錯誤碼驅動流程:所有系統呼叫檢查 CF,統一錯誤處理 — 現代 `HRESULT`/`errno`/例外機制的同源邏輯。

FXN4BH 以不到 100 行核心邏輯,完整實作了「載入器 → 記憶體準備 → 參數封裝 → 系統呼叫 → 狀態恢復 → 繼續執行」的完整生命週期,是理解作業系統程式載入機制、行程建立 API 設計、嵌入式韌體多階段啟動的基石教材。

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