第 11 篇的時候斷賽了,我自己寫文章的速度比較慢,一定要提前準備夠多的篇數,一天一篇對小弟來說很困難,這次準備不足所以決定斷賽,有想過是不是不要按照原來規劃的內容寫少一點,雖然現在的內容也不多,最後還是決定不要這樣,之後有時間再慢慢補齊,感謝有在發摟我的大大,明年會繼續參加希望能順利完賽。
這篇要將我們前面學到的數據段、代碼段、棧段還有其他概念應用在程式中。
首先要提,為什麼要將程式分段呢?
前面有提到分段類似高階語言模組化的概念,將程式依功能區分開來以後較好維護,畢竟程式是寫給以後維護的人看,維護的人也可能是自己。
還記的每個段只能存放 64 KB 大小的數據嗎,大部分的程式都超過了這個限制,程式太長也需要分段。
可將段的名稱當成地址引用,例如程式中定義了段 abc, mov ax, abc
就代表將 abc 的 段地址
放入 ax 暫存器,類似標號的用法。
題目如下歡迎大家一起挑戰。
將下列程式中的英文字母 a-h
反轉成 h-a
存放在原記憶體位置上。
data segment
db 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'
data ends
字母反轉: 提到 反轉
有沒有想到之前介紹的棧,棧的特性是 後進先出
後入棧的項目會先出棧,因此只需將字母依序入棧再出棧,順序就反轉過來了。
字母為字節數據: 字母在記憶體中是以字節型態儲存,而 push、pop 指令只能操作字型數據,因此棧段需要宣告為 dw,並且出棧時只取 低位
的部分。
loop指令: 字母出棧和入棧的動作可用循環指令 loop + [bx]
完成。
程式碼:
assume cs:code, ds:data, ss:stack
data segment
db 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'
data ends
stack segment
dw 0, 0, 0, 0, 0, 0, 0, 0 ; 定義棧空間,型態為字型數據
stack ends
code segment
start:
mov ax, data ; 將 data 的地址放到 ax 暫存器
mov ds, ax ; 將 ax 的值放到 ds 暫存器
mov ax, stack ; 將 stack 的地址放到 ax 暫存器
mov ss, ax ; 將 ax 的地址放到 ss 暫存器
mov sp, 25 ; 設置棧頂位置 8 + 16 + 1
mov bx, 0 ; 設置 bx 指向數據段的第一個位置
mov cx, 8 ; 指定迴圈次數為8
s1:
push [bx] ; 將 [bx] 位置的字母入棧
inc bx ; 將 bx 累加一
loop s1
mov bx, 0 ; 重置 bx
mov cx, 8 ; 重置 cx
s2:
pop ax ; 將字母出棧後先放入 ax 暫存器
mov [bx], al ; 將暫存器低位的數據寫入 [bx] 位置
inc bx ; 將 bx 累加一
loop s2
mov ax, 4c00h ; 退出程式
int 21h ; 調用系統功能
code ends
end start
結果如下:
這篇將之前介紹的概念實際運用在程式上,例子中用到 程式分段
、棧後進先出的特性
、[bx]
、loop 循環
、和使用低位暫存器將 dw 存入 db 中
,學程式還是要有題目練習才學得快,下一篇也會有練習題歡迎大家一起挑戰,今天就到這裡摟,感謝大家觀看。