第七章:更靈活的定位內存地址的方法05
?讓編程改變世界
Change the world by program
?
問題7.8
? [codesyntax lang="asm"]assume cs:codesg,ds:datasg datasg segment db 'ibm ' db 'dec ' db 'dos ' db 'vax ' datasg endscodesg segment start: mov ax,datasgmov ds,axmov bx,0mov cx,4s0: mov si,0mov cx,3s: mov al,[bx+si]and al,11011111bmov [bx+si],alinc siloop sadd bx,16loop s0mov ax,4c00hint 21h codesg ends end start[/codesyntax] 仔細閱讀上面的程序,看看有什么問題? 思考后請聽小甲魚分析! ?
問題7.8分析
? 問題在于cx的使用,我們進行二重循環,卻只用了一個循環計數器,造成在進行內層的時候覆蓋了外層循環的循環計數值。 多用一個計數器又不可能,因為loop指令默認cx為循環計數器。 怎么辦呢? ? 我們應該在每次開始內層循環的時候,將外層循環的cx中的數值保存起來,在執行外層循環的loop指令前,再恢復外層循環的cx數值。 我們可以用寄存器dx來臨時保存cx中的數值。 看看我們改進后的程序(下載源代碼) ? 上面的程序用dx來暫時存放cx中的值。如果在內層循環中,dx寄存器也被使用,該怎么辦? 我們似乎可以使用別的寄存器,但是CPU中的寄存器數量畢竟是有限的,如8086CPU只有14個寄存器。 在上面的程序中:si、cx、ax、bx,顯然不能用來暫存cx中的值,因為這些寄存器在循環中也要使用;
cs、ip、ds也不能用,因為cs:ip時刻指向當前指令,ds指向datasg段;
可用的就只有:dx、di、es、ss、sp、bp等6個寄存器了。 ? 可是如果循環中的程序比較復雜,這些寄存器也都被使用的話,那么該如何? 我們在這里討論的問題是,程序中經常需要進行數據的暫存,我們怎樣做將更為合理。 這些數據可能是寄存器中的,也可能是內存中的。 我們可以用寄存器暫存它們,但是這不是一個一般化的解決方案,因為寄存器的數量有限,每個程序中可使用的寄存器都不一樣。 ? 我們希望尋找一個通用的方案,來解決這種在編程中經常會出現的問題。 顯然,我們不能選擇寄存器,那么可以使用的就是內存了。 我們可以考慮將需要暫存的數據放到內存單元中,需要使用的時候,再從內存單元中恢復。這樣我們就需要開辟一段內存空間。 一起來看再次改進的程序(下載源代碼) ? 改造后的程序中,用內存單元來保存數據。可是上面的作法卻有些麻煩,因為如果需要保存多個數據的時候,讀者必須要記住數據放到了哪個單元中,這樣程序容易混亂。 我們使用內存來暫存數據,這一點是確定了的,但是值得推敲的是,我們用怎樣的結構來保存這些數據,而使得我們的程序更加清晰,更容易讀懂和被接受? ?