第6章 相同的功能 不同的代碼

第六章 相同的功能 不同的代碼


上一章我們分別將每一個顯示字符打入顯示緩衝區,這樣太麻煩,每次修改顯示不同內容得重寫,所以我們這一章設一個專門存放字符串的數據區,當要顯示時,再用指令統一取出來。

補課:除法指令div

8086處理器除法指令有兩種類型。

  • 類型一:16位數除以8位數。被除數放置於ax,除數可以由8位通用寄存器或內存單元提供。商在寄存器al中,餘數在寄存器ah中。
div cl		;除以cx寄存器低位的8位cl
div byte [0x0023]	;除以0x0023處的1字節數據
  • 類型二:32位數除以16位數。因爲16位處理器無法直接提供32位數,所以要求被除數的高16位在dx中,低16位在ax中。商在ax中,餘數在dx中。
div cx
div word [0x0230]

6.5 段之間的批量數據傳送


         jmp near start
         
  mytext db 'L',0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,' ',0x07,'o',0x07,\
            'f',0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07
  number db 0,0,0,0,0
  
  start:
         mov ax,0x7c0                  ;設置數據段基地址 
         mov ds,ax
         
         mov ax,0xb800                 ;設置附加段基地址 
         mov es,ax
         
         cld
         mov si,mytext                 
         mov di,0
         mov cx,(number-mytext)/2      ;實際上等於 13
         rep movsw

因爲計算機啓動時從硬盤啓動,那麼ROM-BIOS將讀取主引導扇區的內容,將它加載到內存地址0x0000:0x7c00處。而每一條mov指令,如果不指定段寄存器的話,都採用"DS指令右移4位+操作數地址"作爲目標地址。此處如果將數據段寄存器ds設爲0x7c0,則由於這段代碼的初始地址就是0x7c00,則可以從這個地方開始,下面自動用ds計算偏移,不用每次都指定地址了。

附加段基址爲0xb800,因爲文本模式的顯示緩衝區首地址就是0xb800,我們要控制movsw指令向顯示緩衝區寫數據,來顯示數據到屏幕上。

上述代碼顯然可看出,35行爲數據段,而718行爲代碼段。按照數據代碼分開儲存的原則,這樣顯然是不對的。但是看到有指令jmp將運行順序跳過了數據區,則可以。

第3行的**\符號**,應該爲不中斷換行符,將下一行的內容同樣也作爲本行,接到後面,這樣就不用在同一行中打印太多內容。

批量數據傳送指令movsb與指令movsw

movsb以字節爲單位傳送,movsw以字(2字節)爲單位傳送。

需要設置以下參數:源數據串地址、目標地址、傳送計數、正向/反向傳送指定標誌。

  • 源數據串地址:在DS:SI指定。
  • 目標地址:在ES:DI指定。
  • 傳送計數:在CX指定。如果是movsb,就設置爲傳送的字節數;如果是movsw,就設置爲傳送的字數(字節數/2)。
  • 正向、反向傳送指定標誌:正向傳送是指從低地址到高地址傳送;反向傳送是指從高地址到低地址傳送。無操作數指令cld意爲將標誌寄存器的第10位DF置爲0,表示正向傳送;std將DF置爲1,表示反向傳送。標誌寄存器的第6位即爲ZF,即零標誌位。每條邏輯或者算數指令後,如果結果爲0,則修改ZF爲1,如果結果爲1,則修改ZF爲0.

每次移動後,DI或SI均+1或+2(正向),-1或-2(反向);無論正反,CX均-1。

單純的movsw或movsb只能執行一次,如果將整個區間全都讀入,則需要用rep指令,意爲不斷重複每一步移動過程,直到CX爲0。


         ;得到標號所代表的偏移地址
         mov ax,number
         
         ;計算各個數位
         mov bx,ax
         mov cx,5                      ;循環次數 
         mov si,10                     ;除數 
  digit: 
         xor dx,dx
         div si
         mov [bx],dl                   ;保存數位
         inc bx 
         loop digit
         
         ;顯示各個數位
         mov bx,number 
         mov si,4                      

循環指令loop

重複轉到標號處執行。loop指令做兩件事

  1. 將cx中的值-1
  2. 如果cx不爲零,則轉移到指定位置處執行,如果cx爲零,就順序執行後面的指令

偏移地址寄存器使用限制

對於第11行,相當於把餘數所在的dl的內容賦值給bx中地址指向的存儲單元。注意,如果要用寄存器來提供偏移地址,只能使用BX、SI、DI、BP,使用其他寄存器都是非法的。

自增自減指令:inc、dec

自增指令inc,相當於C語言中的++。可以指定目標格式。下面的格式都是合法的。

inc al
inc byte [bx]		;將(默認)DS:BX地址處的內容(字節)+1
inc word [label_a]	;將指定位置處的字+1

和inc相對的指令是指令dec,自減,其他都和inc相同。

位擴展指令cbw、cwd

cbw: Convert Byte to Word

cwd: Convert Word to Double-word

cbw意思是將AL中的有符號數擴展到整個AX,如AL中爲01001111,則cbw之後AX爲0000000001001111;如果AL爲10001101,則執行cbw後AX爲1111111110001101.

swd是將AX中的數擴展到DX:AX中。

合法的基址變址寄存器格式

INTEL8086處理器只允許以下四種基址變址寄存器組合

[bx+si]
[bx+di]
[bp+si]
[bp+di]

這些組合可以用於任何帶有內存操作數的指令,其他像[bx+ax]、[ax+cx]等都是非法的。

其他標誌位,如PF、OF、AF、CF

  • PF:如果某次計算結果低8位有偶數個1,則PF=1,否則爲0。
  • OF:當進行有符號數計算時,如果結果出現了溢出,則OF=1,其他情況下OF都爲0,無論有無符號數。
  • AF:看運算結果的最後四位,如果發生進位或者借位,則AF=1,否則AF=0。
  • CF:如果某次運算過程中,最高位有向前進位或借位的情況發生,那麼這次計算後CF=1,否則CF-0。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章