關於《匯編語言(王爽)》程序6.3使用16個dw 0的問題


在學習王爽老師《匯編語言》的第6.2節時,在程序6.3代碼中,給出了如下的代碼:

 1 assume cs:code
 2 code segment
 3     dw 0123h, 0456h, 0789h, 0abch,  0123h, 0456h, 0789h, 0abch
 4     dw 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
 5 
 6 start: mov ax,cs
 7     mov ss,ax
 8     mov sp,30h
 9     
10     mov bx,0h
11     mov cx,8
12 s:  push cs:[bx]
13     add bx,2
14     loop s
15 
16     mov bx,0
17     mov cx,8
18 s0: pop cs:[bx]
19     add bx,2
20     loop s0
21 
22     mov ax,4c00h
23     int 21h
24 code ends
25 end start

可以看到第4行中定義了16個dw 0,也就是16個字型數據(32個字節型),隨后將該32個字節內存空間當做棧來使用。初始棧頂為30h,結構圖如下:

從上圖可以看到,總共花費了48個字節,48轉換成16進制值為30H,而內存地址從0開始計數,因此這2個dw的內存起止地址為0~2F,上面的代碼將第二個dw段視作棧空間,初始棧為空,因此指向棧下面的內存空間,結構如下:

所以代碼的第8行將棧偏移地址寄存器SP設置為30h。

這里有一個問題,第一個dw段只定義了8個字型數據(16個字節),為了逆序反轉它,應該只需要8個字型大小的棧空間,但實際卻定義了16個字型數據(32個字節),多出來8個字型數據,似乎是多余的。更改代碼,將第二個dw段中定義的16個字型數據更改為8個,這樣棧偏移地址寄存器SP就應該設置為20h,然后調試程序看看,如下:

首先回憶書本第4章4.9節程序執行過程的跟蹤中的說明,一個程序的加載一定是先找到一段足夠空間的內存,該內存空間的地址段為SA,偏移地址為0,因此寄存器CS=SA,寄存器IP=0h。而該內存前面256個字節用來和程序通信,因此實際的指令段地址為CS=CS+10h。

上機查看加載到內存的代碼指令,可以看到IP寄存器的值的確為20h,因為前面32個字節是數據空間,第33個字節才是真正指令,因此IP指向20h(這是程序源碼中start標志告訴編譯器的)。另外,也可以看到第一個壓棧的循環在0B34:002D~0B34:0033處。

 

在執行循環壓棧數據之前,先查看代碼指令前20個字節的空間的值,也就是2個dw段中定義的數據。然后一次性執行完第一個循環,使用g命令,令其執行到0B34:0035處開始等待,然后再查看一次前20字節的數據空間,如下:

從上圖可以發現一個比較奇怪的地方,那就是棧空間的數據並沒有改變,第一個dw段的數據沒有壓棧。這不應該,為什么沒有正常工作?再次查看代碼指令,突然發現代碼指令被改寫了,如下圖:

由於指令被改寫,那自然上面的程序就沒發正常工作了。那為什么指令的內容會被改變呢?回想書本第3章最后一個問題,也就是實驗2中最后一個提問,為什么棧里的數據改變了?

最前面的程序使用16個dw字型數據做棧空間時,能夠正常工作,而使用8個字型數據時,則出現了問題,這原因是不是和上面圖中的提問的答案一樣?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM