實驗1 —— 用機器指令和匯編指令編程(2)
debug 指令補充
在執行 d
命令時可以帶地址參數 (段地址: 偏移地址),其中的段地址會先被送到 ds
寄存器,再交給處理器。
因此,d
命令也可以這樣用: d SR:offset
(SR指段寄存器)
例如:
-r ds
:1000
-d ds:0 ;查看從 1000:0 開始的內存區間中的內容
-r ds
:1000
-d ds:10 18 ;查看 1000:10 ~ 1000:18 中的內容
-d cs:0 ;查看當前代碼段中的指令代碼
-d ss:0 ;查看當前棧段中的內容
當然 e
命令、a
命令和 u
命令也是一樣的。
例如:
-r ds :1000 -e ds:0 11 22 33 44 55 66 ;在從 1000:0 開始的內存區間中寫入數據
-u cs:0 ;以匯編指令的形式,顯示當前代碼段中的代碼,0 代碼的偏移地址
-r ds
:1000
-a ds:0 ;以匯編指令的形式,向從 1000:0 開始的內存單元中寫入指令
有趣的現象
在執行以下的代碼時,你會發現 t
命令會不管用:
mov ax, 2000 ; 1
mov ss, ax ; 2
mov sp, 10 ; 3
mov ax, 3123 ; 4
push ax ; 5
mov ax, 3366 ; 6
push ax ; 7
單步執行結果如下圖所示:
可見第 2 行和第 3 行代碼一起執行了 (我這裏與書本上的展示不同,可能與軟件版本有關)。
具體是怎麽回事以後深究,我們需要知道的是: 在執行修改 ss 寄存器的指令時,下一條指令會被一並執行。
實驗
本實驗為《匯編語言》(王爽著,第 3 版)第 74 頁 實驗任務
將下面的程序寫入內存,執行並填空:
為了便於驗證實驗結果,對該實驗做如下兩點調整:
- 在使用
a
命令輸入指令調試前,使用e
命令將內存單元0021:0
到0021:7
連續 8 個字節數據修改為30H
,31H
,32H
,33H
,34H
,35H
,36H
,37H
- 將該實驗中第 1 行的
mov ax, ffff
mov ax, 0021
mov ax, 0021 mov ds, ax mov ax, 2200 mov ss, ax mov sp, 0100 mov ax, [0] ; ax = _3130_ add ax, [2] ; ax = _6462_ mov bx, [4] ; bx = _3534_ add bx, [6] ; bx = _6c6a_ push ax ; sp = _00fe_ ; 修改的內存單元的地址是 _220fe_ 內容為 _6462_ push bx ; sp = _00fc_ ; 修改的內存單元的地址是 _220fc_ 內容為 _6c6a_ pop ax ; sp = _00fe_ ; ax = _6c6a_ pop bx ; sp = _0100_ ; bx = _6462_ push [4] ; sp = _00fe_ ; 修改的內存單元的地址是 _220fe_ 內容為 _3534_ push [6] ; sp = _00fc_ ; 修改的內存單元的地址是 _220fc_ 內容為 _3736_
填空已經寫進了註釋,運行結果如下圖所示:
這個實驗在 FreeDOS 中會報錯,如下圖所示:
最後不得不用了 MS-DOS,我分析原因是 FreeDOS 不完全兼容 16 位匯編出現
operand size mismatch
- 在使用
為什麽
2000:0
~2000:f
中的內容會發生改變?運行結果如下圖所示:
仔細觀察執行後
2000:a
到2000:d
內存中的數據,可見正好是依照小端法存儲的cs
和ip
的值,據網上資料所說,這是對定義棧段時部分運行環境變量進行暫存,靠近棧頂的 10 個字節中的暫存數據分別是ss
、ip
、cs
等的值,是否正確我尚未考證,但應該與系統的調度有關。
我認為匯編是計算機專業的必修課,在計算機系統中也好,單獨作為一門課程也罷,真正需要學習的不是怎麽用,這是為了彌補一個計算機專業學生的基本常識。如果只是覺得什麽東西有用而學它,那是沒有回報的。如果你只看到一件事的1%,不代表你看到了它剩下的99%。在一切因素都不確定的情況下,能做好自己本分又有多少。幹些什麽吧,趁自己還年輕。
Invictus maneo.
實驗1 —— 用機器指令和匯編指令編程(2)