- UID
- 460236
- 帖子
- 21
- 主題
- 11
- 精華
- 0
- 積分
- 22
- 楓幣
- 711
- 威望
- 21
- 存款
- 0
- 贊助金額
- 0
- 推廣
- 0
- GP
- 12
- 閱讀權限
- 10
- 性別
- 保密
- 在線時間
- 17 小時
- 註冊時間
- 2024-10-12
- 最後登入
- 2024-11-25
|
本帖最後由 ikj78i 於 2024-11-22 08:21 編輯
堆疊是記憶體中的一塊區域,程式一開始執行時,系統會保留一塊記憶體給堆疊使用。等所有
初始化工作完成,ESP就指向堆疊某處,此位址及比此位址高的記憶體存有系統保留的資料,
比這個位址低的記憶體空間都是空的。此為指稱為堆疊頂。
x86 CPU利用PUSH指令把資料存入堆疊,它的語法是
PUSH 來源運算元
來源運算元可以是暫存器、變數、常數
每當PUSH來源運算元時,ESP會先減少,然後再把來源運算元存入ESP所指的位址。至於減少多
少,要看來源運算元長度。如果是WORD就減少2;如果;是DWORD就減少4。而此時堆疊頂就比原
先少2或少4。像這樣把資料存入堆疊使ESP減少稱為把資料推入堆疊。
而讀取堆疊的資料則用x86指令
POP 目的運算元
目的運算元只能是暫存器、變數
當POP目的運算元時,先把ESP所指的堆疊頂資料存入目的運算元,再使ESP增加。增加多少跟
目的運算元的長度有關。這樣的過程稱為彈出資料。
舉例來說,假如有底下三個指令,X、Y、Z都是字組,ESP為106
堆疊位址 低-->高
指令 ESP 100 102 104 106
PUSH X 106 DDD 尚未執行PUSH X
PUSH Y 104 X DDD 尚未執行PUSH Y,而PUSH X已執行完畢
PUSH Z 102 Y X DDD 尚未執行PUSH Z,而PUSH Y已執行完畢
102 Z Y X DDD PUSH Z已執行完畢
假如現在要把上面三個堆疊的資料依序彈出,且存於位址300處
指令 ESP 100 102 104 106....300 302 304 306
POP [300] 100 Z Y X DDD 尚未執行POP [300]
POP [302] 102 Y X DDD Z 尚未執行POP [302],已執行POP [300]
POP [304] 104 X DDD Z Y 尚未執行POP [304],已執行POP [302]
106 DDD Z Y X 已執行完POP [306]
堆疊有一種很特別的性質,最先推入堆疊的資料,卻是最後才能彈出。上面的例子X是最先推入
堆疊,再彈出後卻是在最高位址。由於堆疊有這種特性,很適合把資料做倒敘排列(就是先後順
序顛倒)
回文詩是中文特有的詩體,正讀與倒讀都有意義,例如底下的例子:- ;底下的PALINDROME.ASM把宋朝李禺兩相思的正文夫思妻,回文後變妻思夫
- ;此程式利用堆疊先進後出的特性就能造成回文詩的效果。
- .586
- .model flat,stdcall
- option casemap:none
- include c:\masm32\include\windows.inc
- include c:\masm32\include\kernel32.inc
- includelib c:\masm32\lib\kernel32.lib
- ;*******************************************************************************
- .DATA
- hOut DD ?
- dOut DD ?
- author DB "《兩相思》 宋 李禺",0dh,0ah
- poem DB "枯眼遙望山隔水,往來曾見幾心知。",0dh,0ah
- DB "壺空怕酌一杯酒,筆下難成和韻詩。",0dh,0ah
- DB "途路阻人離別久,訊音無雁寄回遲。",0dh,0ah
- DB "孤燈夜守長寥寂,夫憶妻兮父憶兒。",0dh,0ah
- palindromed DB 0dh,0ah,"回文後:",0dh,0ah
- poem_size EQU OFFSET palindrome_poem-OFFSET author
- poem_text_size EQU OFFSET palindromed-OFFSET poem
- palindrome_poem DB poem_text_size+4 DUP (0)
- ;*******************************************************************************
- .CODE
- ;-------------------------------------------------------------------------------
- ;-------------------------------------------------------------------------------
- main PROC
- invoke GetStdHandle,STD_OUTPUT_HANDLE
- mov hOut,eax
- invoke WriteConsole,hOut,OFFSET author,poem_size,OFFSET dOut,0
- ;把正文推入堆疊
- lea edx,poem
- mov ecx,17*4 ;每列包含標點符號及換行符號共17個字組,有4列
- next1: push WORD PTR [edx] ;從peom字串的第一個字組推入堆疊,它在堆疊最高位址
- add edx,2 ;而後依次把下個字組推入堆疊,存放位址越來越低
- loop next1
- ;由堆疊中取回(彈出)詩文,存放於palindrome_poem
- mov ecx,17*4 ;堆疊內已存放17*4個字組
- lea edx,palindrome_poem ;資料由堆疊彈出後的存放位址
- next2: pop WORD PTR [edx] ;彈出一個字組,存放於EDX所指的位址
- add edx,2 ;每彈出一個堆疊,EDX所指位址往後增加2
- loop next2
- ;處理每列最後面的標點符號及換行符號,它們必須交換位置
- mov ecx,3
- lea edx,palindrome_poem
- add edx,34
- next3: mov ax,[edx]
- xchg ax,[edx+2]
- mov [edx],ax
- add edx,34
- loop next3
- ;處理最後一行的句號
- mov WORD PTR[edx],043a1h
- invoke WriteConsole,hOut,OFFSET palindrome_poem+4,poem_text_size,OFFSET dOut,0
- invoke ExitProcess,0
- main ENDP
- ;*******************************************************************************
- END main
複製代碼 依下面步驟組譯、連結並執行:
|
-
PA.png
(15.02 KB, 下載次數: 0)
李禺兩相思
|