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

DOS 時代組合語言經典:EXECSUB 子程序調用實現

     編輯:組合語言

概述

EXECSUB 是一個用於 Microsoft 編譯版 BASIC(QuickBASIC/QB)調用外部程序的組合語言子程序。它允許 BASIC 程序通過 CALL EXECSUB(PROG$, PARM$, FCB1$, FCB2$, RETCD%) 方式加載並執行另一個可執行文件(如 COMMAND.COM 或其他 .EXE/.COM),並支持傳遞命令行參數、兩個 FCB(文件控制塊)以及獲取返回碼。該代碼展示了 DOS 2.0+ 環境下 INT 21h/4Bh(加載並執行)的完整封裝過程,包括中斷向量保存/恢復、內存縮減、參數塊構建、棧切換等關鍵步驟。

核心技術點

1. 中斷向量的保存與恢復

BASIC 運行時會佔用 INT 1Bh (Ctrl-Break)、INT 1Ch (Timer Tick)、INT 24h (Critical Error) 等中斷。執行子程序前必須將這些向量保存,並恢復 BASIC 的影子向量(B1BIP/B1BCS 等),否則子程序運行期間 BASIC 的中斷處理會失效。代碼通過 CLI/STI 關中斷/開中斷保護操作原子性。

2. 內存縮減(INT 21h/4Ah)

獲取 PSP 段地址(ES:[0002h] 存儲段落數),計算當前程序佔用內存,釋放多餘內存給子程序使用。若失敗返回錯誤碼 0。

3. 參數塊構建(EXEC 參數結構)

  • prm1:環境段地址(0 表示繼承父進程環境)
  • prm2:命令行指針(DS:DX 指向參數字符串,以 0Dh 結尾)
  • prm3/prm4:兩個默認 FCB 指針(DS:SI 格式)

代碼從 BASIC 字符串描述符(skip=2 跳過長度字)提取偏移/段地址填入參數塊。

4. 棧切換與執行

保存當前 SS:SP 到 stak,調用 INT 21h/4Bh AL=0 加載並執行。子程序結束後恢復棧、恢復中斷向量、恢復 BASIC 的 DS,最後將返回碼寫入 RETCD%。

代碼結構說明

; EXECSUB - execute program from compiled BASIC - requires DOS 2.00
; CALL EXECSUB(PROG$,PARM$,FCB1$,FCB2$,RETCD%)
cseg segment para public 'code'
public execsub
execsub proc far
 assume cs:cseg,ds:cseg,ss:nothing,es:nothing
basicds equ 510h          ; BASIC 數據段地址(在 PSP:510h)
i24ip equ 90h             ; INT 24h 向量偏移
i24cs equ 92h
i1bip equ 6ch             ; INT 1Bh 向量
i1bcs equ 6eh
i1cip equ 70h             ; INT 1Ch 向量
i1ccs equ 72h
b24ip equ 51ah            ; BASIC 影子向量
b24cs equ 51ch
b1bip equ 516h
b1bcs equ 518h
b1cip equ 512h
b1ccs equ 514h
; ... 保存向量、縮減內存、構建參數塊、棧切換、執行、恢復現場 ...
execsub endp
cseg ends
end

歷史價值與現代啟示

該代碼是早期混合語言編程(BASIC + ASM)的典型樣本,展示了:

  • 實模式下進程加載的完整流程
  • 中斷向量表操作的細節
  • 參數塊與 FCB 的傳遞約定
  • 棧切換與上下文保存的標準模式

雖然現代系統不再使用 DOS 實模式,但「保存上下文 → 準備參數 → 調用執行器 → 恢復上下文」的模式在作業系統內核、虛擬機監控器、沙箱隔離等領域依然普遍存在。

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