組合語言(第3版) 第11章相關內容及實驗11
第十一章 標誌暫存器
文章目錄
章節內容
概述
主要介紹了標誌暫存器和其中的CF,PF,ZF,SF,OF,DF標誌位。
標誌暫存器的作用:
- 用來儲存相關指令的某些執行結果
- 用來為CPU執行相關指令提供行為依據
- 用來控制CPU的相關工作方式
8086CPU 的 flag 暫存器結構:
8086CPU指令集中:add、sub、mul、div、inc、or、and等(大多為運算指令)指令執行會影響標誌暫存器。
像 mov、push、pop等(大多是傳送指令)指令執行不影響標誌暫存器。
本章還介紹了與標誌暫存器有關的adc、sbb、cmp、movsb、movsw、pushf、popf等指令。
ZF標誌
flag的第6位,零標誌位,若相關指令執行後結果為0,則zf=1,否則zf=0;
PF標誌
flag的第2位,奇偶標誌,若相關指令執行後結果中所有bit位中1的個數為偶數,則pf=1,否則pf=0;
SF標誌
flag的第7位,符號標誌位,若相關指令執行後結果為負,則sf=1,否則sf=0;
CF標誌
flag的第0位,進位標誌位,在進行無符號數運算時,記錄運算結果的最高有效位向更高位的進位值,或從更高位的借位值,進位/借位了cf=1,否則cf=0;
OF標誌
flag的第11位,溢位標誌位,在進行有符號數運算時,記錄運算結果是否發生了溢位,溢位了of=1,否則of=0;
(如進行8位暫存器或記憶體單元有符號運算,超過範圍-128~127為溢位,16位有符號運算,超過範圍-32768~32767為溢位)
CF和OF所表示的進位和溢位,分別是對無符號數和有符號數運算而言的,他們之間沒有任何關係。
DF標誌
flag的第10位,方向標誌位,在串處理指令中,控制每次操作後si、di的增減。
df=0,每次操作後si、di遞增。
df=1,每次操作後si、di遞減。
cld指令設定df=0
std指令設定df=1
串傳送指令會在後文介紹。
adc/sbb指令
帶進位加法/帶借位減法指令,利用了CF位上記錄的進位/借位值。
指令格式: adc 操作物件 1,操作物件 2
功能: 操作物件 1 = 操作物件 1 + 操作物件 2 + CF
指令格式: sbb 操作物件 1,操作物件 2
功能: 操作物件 1 = 操作物件 1 - 操作物件 2 - CF
cmp指令與檢測比較結果的條件轉移指令
cmp是比較指令,相當於不儲存結果的減法,但是會對標誌暫存器產生影響,其他若干指令通過識別被影響的暫存器位得知比較結果。
指令格式: cmp 操作物件 1,操作物件 2
功能: 計算操作物件 1 - 操作物件 2 但不儲存結果,根據計算結果對標誌暫存器進行設定
檢測比較結果的條件轉移指令:
指令 | 字母表示意義 | 含義 | 檢測的相關標誌位 |
---|---|---|---|
je | jump equal | 等於則轉移 | zf=1 |
jne | jump not equal | 不等於則轉移 | zf=0 |
jb | jump below | 低於則轉移 | cf=1 |
jnb | jump not below | 不低於則轉移 | cf=0 |
ja | jump above | 高於則轉移 | cf=0 且 zf=0 |
jna | jump not above | 不高於則轉移 | cf=1 或 zf=1 |
這些常與cmp配合使用。
注意,對於有符號數和無符號數,這些指令檢測的標誌位可能會不同,但這裡不做詳細探究。(指令的重點不在這)
串傳送指令
movsb
執行相當於以下幾步驟
( (es)*16+(di) ) = ( (ds)*16+(si) )
根據df標誌位的值遞增/遞減1
movsw
與movsb類似,但每次傳送一個字
( (es)*16+(di) ) = ( (ds)*16+(si) )
根據df標誌位的值遞增/遞減2
movsb/movsw常與rep配合使用構成一個串傳送操作。
格式為rep movsb
/ rep movsw
rep根據cx的值,重複執行若干次之後的串傳送指令。
相當於組合語言下的
s: movsb
loop s
;以及
s: movsw
loops
從而實現(cx)個字元或字的傳送,由df標誌位控制方向(遞增或遞減)
pushf和popf指令
pushf將標誌暫存器的值壓棧,popf將棧中的值彈出送入標誌暫存器中。
標誌暫存器在Debug中的表示
Debug中標誌暫存器的各個位是單獨表示的。
如圖:
各標誌位的表示:
標誌 | 值為1的標記 | 值為0的標記 |
---|---|---|
of | OV | NV |
sf | NG | PL |
zf | ZR | NZ |
pf | PE | PO |
cf | CY | NC |
df | DN | UP |
實驗11 編寫子程式
編寫子程式,將包含任意字元,以0結尾的字串中的小寫字母轉變成大寫字母。
名稱:letterc
功能:將以0結尾的字串中的小寫字母轉變成大寫字母
引數:ds:si指向字串首地址。
需要用到本章學習的cmp和條件轉移指令判斷一個字元是否為小寫字母,其他就挺簡單了。
程式碼如下:
assume cs:codesg
datasg segment
db "Beginner's All-purpose Symbolie Instruction Code.",0
datasg ends
stacksg segment
db 16 dup (0)
stacksg ends
codesg segment
begin :
mov ax,datasg
mov ds,ax
mov si,0
mov ax,stacksg
mov ss,ax
mov sp,16
call letterc
mov ax,4c00h
int 21h
letterc:
;暫存器入棧
push si
push cx
mov ch,0
;子程式
letterc_begin:
mov cl,[si]
jcxz betterc_ok
cmp cl,'a'
jb letterc_next
cmp cl,'z'
ja letterc_next
and cl,11011111b
mov [si],cl
letterc_next:
inc si
jmp short letterc_begin
betterc_ok:
;暫存器出棧
pop cx
pop si
ret
codesg ends
end begin
結果: