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

深入解析組合語言中的堆疊操作與地址計算

     編輯:組合語言

這篇文章旨在釐清組合語言中堆疊操作的地址計算細節,透過一個具體的範例程式,詳細說明 push 與 pop 指令對堆疊指標(SP)的影響,以及如何正確設定初始堆疊指標與資料來源指標。

核心概念回顧

在 8086 架構中,堆疊相關的關鍵暫存器與指令包括:

  • SS (Stack Segment):堆疊段暫存器
  • SP (Stack Pointer):堆疊指標,指向堆疊頂端
  • PUSH:壓入堆疊(SP 先減 2,再寫入資料)
  • POP:彈出堆疊(先讀取資料,SP 再加 2)

關鍵機制:先減後存、先取後加

這是理解堆疊地址計算的核心:

  • PUSH 操作:處理器先將 SP 減 2,然後將資料的高位元組寫入 [SS:SP],低位元組寫入 [SS:SP+1]。簡單說,SP 先指向下一個可用位置,再存入資料。
  • POP 操作:處理器先從 [SS:SP] 讀取低位元組,[SS:SP+1] 讀取高位元組,組合成字資料,然後將 SP 加 2。即 先取資料,SP 再後移。

實戰範例:將資料段 A 前 8 個字按序存入堆疊段 B

假設段 A 有 15 個字資料(1 到 0FH),段 B 預留 8 個字空間。目標是將 A 段的前 8 個字(偏移 0~14H)依序壓入 B 段作為堆疊,最終 B 段從低地址到高地址應存放 1, 2, ..., 8。

程式框架與關鍵填空

mov ax, b        ; 設定堆疊段
mov ss, ax
mov sp, _______  ; ★ 填空 1:初始 SP 值
mov ax, a        ; 設定資料段
mov es, ax
mov bx, _______  ; ★ 填空 2:來源資料偏移
mov cx, 8
loop1:
  push es:[bx]   ; 壓入資料
  sub bx, 2      ; 指向前一個字
  loop loop1

填空 1:初始 SP = 10H (16)

B 段有 8 個字,佔 16 位元組(偏移 0~0FH)。第一次 PUSH 會先將 SP 減 2。為了讓第一筆資料(A 段第 8 個字,值 8)落在 B 段第 8 個字位置(偏移 0EH~0FH),SP 減 2 後必須指向 0EH。因此初始 SP = 0EH + 2 = 10H。

驗證:SP=10H → PUSH 時 SP=0EH → 寫入偏移 0EH/0FH(第 8 個字)。正確。

填空 2:來源 BX = 0EH (14)

A 段第 8 個字(值 8)的偏移為 (8-1)*2 = 14 = 0EH。迴圈每次 sub bx, 2 往前取值,依序取得 8, 7, ..., 1。

完整程式碼

assume cs:codeseg
a segment
  dw 1,2,3,4,5,6,7,8,9,0aH,0bH,0cH,0dH,0eH,0fH
a ends
b segment
  dw 0,0,0,0,0,0,0,0
b ends
codeseg segment
start:
  mov ax, b
  mov ss, ax
  mov sp, 10H          ; 初始堆疊指標
  mov ax, a
  mov es, ax
  mov bx, 0EH          ; 來源偏移:第 8 個字
  mov cx, 8
loop1:
  push es:[bx]
  sub bx, 2
  loop loop1
  mov ax, 4c00H
  int 21H
codeseg ends
end start

除錯驗證

執行後查看記憶體,B 段(SS:0000)將依序顯示:

0000: 0001 0002 0003 0004 0005 0006 0007 0008

完全符合預期。同樣邏輯適用於 POP 操作,讀者可自行嘗試。

總結

堆疊操作的地址計算關鍵在於 SP 的預減/預增機制。設定初始 SP 時,必須考慮第一次操作前的指標變化;存取資料時,索引暫存器(BX/SI/DI)直接指向目標資料當前位址。掌握這一點,即可避免堆疊溢位、資料錯位等常見錯誤。

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