第六章 相同的功能 不同的代碼
上一章我們分別將每一個顯示字符打入顯示緩衝區,這樣太麻煩,每次修改顯示不同內容得重寫,所以我們這一章設一個專門存放字符串的數據區,當要顯示時,再用指令統一取出來。
補課:除法指令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指令做兩件事
- 將cx中的值-1
- 如果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。