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

8086/88 記憶體定址模式圖解與實戰範例

     編輯:組合語言

前言

8086/88 採用分段式記憶體架構,物理位址 = 段基址 × 16 + 偏移位址 (即 段基址 << 4 + 偏移)。理解五種基本定址模式,是撰寫高效組語、分析程式碼、除錯的基礎。本文以「大樓-單元-門牌」比喻直觀解釋,並提供 DEBUG 實際輸出與完整程式範例驗證。

記憶體定址比喻:大樓、單元、門牌

  • 段基址 (Segment):大樓號碼 (如 0B1Fh)
  • 偏移位址 (Offset):單元號碼 (如 0100h)
  • 有效位址 / 變址 (Effective Address):門牌號碼 (單元內的 0~15 號房間)
  • 物理位址:大樓 × 16 + 單元 + 門牌 = 絕對位置

DEBUG D 命令輸出範例:

0B1F:0100  00 80 FF 02 75 05 C6 46-00 00 C3 E8 8C EB B4 3B
          ↑                    ↑
        單元 0100h           門牌 0~F (16 字節/行)

五種基本定址模式詳細解析

1. 暫存器直接定址

概念:已站在門口,直接敲門進入。操作數在指令中直接給出位移量,預設段為 DS。

MOV AX, [2000H]    ; 讀取 DS:2000h 字組
MOV AX, 2000H      ; 立即數載入 AX,非記憶體存取

物理位址 = DS × 16 + 2000h

2. 暫存器間接定址

概念:站在單元門口,知道目標在該單元的第幾樓 (暫存器值)。使用 BX、SI、DI、BP 存放偏移量。

MOV AX, [BX]       ; DS:BX
MOV AX, [SI]       ; DS:SI
MOV AX, [DI]       ; DS:DI
MOV AX, [BP]       ; SS:BP (預設段為 SS)

物理位址 = DS × 16 + BX (或 SI/DI) / SS × 16 + BP

3. 暫存器相對定址

概念:目標在你家樓上/樓下幾層 (位移量 + 暫存器)。

MOV AX, COUNT[SI]      ; 等價於 [COUNT + SI]
MOV AX, [COUNT + SI]   ; COUNT 為位移常數

物理位址 = DS × 16 + SI + 位移量 (8/16-bit 位移) / SS × 16 + BP + 位移量

4. 基址變址定址

概念:同棟大樓不同單元,需知道單元號 (BX/BP) 與樓層 (SI/DI)。

MOV AX, [BX][DI]       ; 等價於 [BX + DI]
MOV AX, [BP][SI]       ; SS:BP+SI

物理位址 = DS × 16 + BX + SI/DI / SS × 16 + BP + SI/DI

5. 相對基址變址定址

概念:結合位移量 + 基址暫存器 + 變址暫存器,最靈活的定址方式。

MOV AX, MASK[BX][SI]   ; 等價於 [MASK + BX + SI]
MOV AX, [MASK + BX + SI]

物理位址 = DS × 16 + BX + SI/DI + 位移量 / SS × 16 + BP + SI/DI + 位移量

定址模式速查表

模式指令範例預設段物理位址計算可用暫存器組合
直接MOV AX, [2000H]DSDS×16 + 2000H無
間接MOV AX, [BX]DSDS×16 + BXBX, SI, DI
間接MOV AX, [BP]SSSS×16 + BPBP
相對MOV AX, 10H[SI]DSDS×16 + SI + 10HBX, SI, DI, BP
基址變址MOV AX, [BX][DI]DSDS×16 + BX + DIBX/BP + SI/DI
相對基址變址MOV AX, TABLE[BX][SI]DSDS×16 + BX + SI + TABLEBX/BP + SI/DI + 位移

實戰範例:字串倒序輸出

功能:輸入字串 (最多 9 字元),按 Enter 後倒序顯示。展示 暫存器間接定址 存取緩衝區長度與字元。

data segment
user_string db 10, 0, 10 dup(?)   ; DOS 緩衝區格式:最大長度、實際長度、資料區
data ends

code segment
assume cs:code, ds:data
start:
    mov ax, data
    mov ds, ax
    lea dx, user_string           ; DX = 緩衝區位移
    mov ah, 0Ah                   ; DOS 0Ah: 帶回顯的字串輸入
    int 21h

    xor si, si
    xor bx, bx
    mov bx, dx                    ; BX = 緩衝區基址
    mov cx, [bx + si + 1]         ; 間接定址讀取「實際長度」 (Offset 1)
    xor ch, ch                    ; 清高位,CX = 長度
    mov di, cx                    ; DI = 索引,指向最後一字元

lop:
    mov ah, 2                     ; DOS 2h: 顯示字元 (DL)
    mov dx, [bx + di + 1]         ; 間接定址讀取字元 (資料區起始 Offset 2,故 +1)
    int 21h
    dec di
    loop lop                      ; CX 遞減至 0 結束

    mov ah, 4Ch
    int 21h
code ends
end start

關鍵指令解析

  • MOV CX, [BX + SI + 1]:BX 基址 (緩衝區開頭),SI=0,位移 1 → 讀取「實際輸入長度」位元組。
  • MOV DX, [BX + DI + 1]:DI 從長度-1 遞減至 0,位移 1 (跳過長度位元組) → 依序讀取最後一字元至第一字元。
  • LOOP LOP:CX 為計數器,自動 DEC CX / JNZ,極適合已知次數迴圈。

DEBUG 驗證技巧

  1. 組譯連結生成 .EXE,用 DEBUG PROG.EXE 載入。
  2. R 檢視暫存器,U 反組譯確認指令編碼。
  3. G 執行,輸入測試字串觀察輸出。
  4. D DS:OFFSET 檢視緩衝區內容結構 (長度位元組、資料區)。

總結

掌握五種定址模式的物理位址計算、預設段暫存器、指令編碼差異,能讓您:

  • 撰寫高密度、高效能的記憶體存取代碼。
  • 閱讀反組譯碼時快速判斷存取意圖。
  • 除錯時精確定位記憶體錯誤 (如段暫存器設錯導致存取錯誤區域)。

建議配合 DEBUG 實機操作,觀察暫存器與記憶體變化,建立直觀的分段定址心智模型。

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