匯編入門學(xué)習(xí)筆記 (十)—— 標(biāo)志寄存器、串傳送指令
參考: 《匯編語言》 王爽 第11章
CPU內(nèi)部有一種特殊的寄存器叫標(biāo)志寄存器(flag),它與ax,bx,cx等其他寄存器不同,它不是用來存放數(shù)據(jù)的,而是用來存放狀態(tài)的。flag寄存器是按位器作用的,即只有0和1。
flag寄存器的結(jié)構(gòu):
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OF DF IF SF ZF AF PF CF
在debug中標(biāo)志位的表示:
標(biāo)志 1 0
of OV NV
sf NG PL
zf ZR NZ
pf PE PO
cf CY NC
df DN UP
1. ZF標(biāo)志
零標(biāo)志位。如果上條相關(guān)指令結(jié)果為0,那門ZF=1,不為0那門ZF=0
例子:
- movax,1
- subax,1
- movax,1
- andax,0
執(zhí)行后zf為1
add,sub,mul,div,inc,or,and等這些運算指令會影響標(biāo)志寄存器
mov,push,pop等轉(zhuǎn)移指令對標(biāo)志寄存器沒有影響
2. PF 標(biāo)志
奇偶標(biāo)志位。是0是1的規(guī)則 ,類似于奇校驗。
如果上條相關(guān)指令結(jié)果二進制中1的個數(shù)為偶數(shù),則PF=1,為奇數(shù)則PF=0 。
例子:
- moval,1
- addal,10
al = 00001011b
pf = 0
- moval,1
- oral,2
al = 00000011b
pf = 1
3. SF標(biāo)志
符號標(biāo)志位。
如果上條相關(guān)指令結(jié)果為負(fù)數(shù),則SF=1,正數(shù)則SF=0
本質(zhì)就是看第一位是否為1
- moval,10000001b
- addal,1
SF = 1
4. CF標(biāo)志
表示無符號計算中的進位(注意:inc和dec指令是不影響CF的,但會影響ZF與OF)
例子:
- moval,98H
- addal,al
CF = 1
相減為負(fù)數(shù),也會使得CF = 1
- movax,1
- subax,2
5. OF標(biāo)志
表示有符號計算的溢出(注意:inc和dec指令是會影響OF的)
例如8位補碼 表示的數(shù)的范圍 -128~127
例子:
- moval,0F0H
- addal,88H
-16+(-120) = -136
超過了范圍,所以O(shè)F = 1
6. abc 指令
帶進位的加法指令
abc ax,bx
相當(dāng)于(ax)=(ax)+(bx)+CF
例子:實現(xiàn)兩個128位數(shù)據(jù)相加
- assumecs:code,ds:data
- datasegment
- db88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h
- db11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h
- dataends
- codesegment
- start:movax,data
- movds,ax
- movsi,0
- movdi,16
- movcx,8
- calladd128
- add128:pushax
- pushcx
- pushsi
- pushdi
- subax,ax;將CF設(shè)置為0
- s:movax,[si]
- adcax,[di]
- mov[si],ax
- incsi;不用add是因為add會改變CF的值
- incsi
- incdi
- incdi
- loops
- popdi
- popsi
- popcx
- popax
- codeends
- endstart
7. sbb指令
sbb是帶借位的減法指令
sbb ax,bx 相當(dāng)于(ax)=(ax)-(bx)-CF
8. cmp指令
cmp是比較指令,相當(dāng)于減法,但不保存結(jié)果只改變flag
cmp ax,bx
對于無符號數(shù)來說
如果(ax)=(bx) 則(ax)-(bx)=0, 所以:zf = 1;
如果(ax)!=(bx) 則(ax)-(bx)!=0,所以:zf = 0;
如果(ax)< (bx) 則(ax)-(bx)會產(chǎn)生錯位,所以:cf = 1;
如果(ax)>(bx) 則(ax)-(bx)不會產(chǎn)生錯位,結(jié)果也不可能為0, 所以:cf = 0 并且zf = 0;
可以這么說:
zf = 1 說明(ax)=(bx)
zf = 0 說明(ax)!=(bx)
cf = 1 說明(ax)< (bx)
cf = 0 說明 (ax)>= (bx)
cf = 0 并且zf = 0 ,說明(ax)>(bx)
cf = 1 或者zf=1, 說明 (ax)<=(bx)
對于有符號數(shù)來說
zf = 1 說明(ax)=(bx)
zf = 0 說明(ax)!=(bx)
sf=1 并且 of=0,說明(ax)<(bx)sf=0 并且 of=1,說明(ax)<(bx)
sf=1 并且 of=1,說明(ax)>(bx)
sf=0 并且 of=0,說明(ax)>=(bx)
9. 檢測比較結(jié)果的條件轉(zhuǎn)移指令
對于無符號數(shù):
je 等于則轉(zhuǎn)移 zf=1
jne 不等于則轉(zhuǎn)移 zf=0
jb 低于則轉(zhuǎn)移 cf=1
jnb 不低于則轉(zhuǎn)移 cf=0
ja 高于則轉(zhuǎn)移 cf=0且cf = 0
jna 不高于則轉(zhuǎn)移 cf=1或zf=1
各個字母的意思:
j:jmp
e:equal
ne:not equal
b:below
nb:not below
a:above
na:not above
例如實現(xiàn):如果(ah)=(bh)則(ah)=(ah)+(ah),否則(ah)=(ah)+(bh)
- cmpah,bh
- jes
- addah,bh
- ddah,ah
例子:計算data段中為8的數(shù)的個數(shù),記錄在ax中
- assumecs:code,ds:data
- datasegment
- db8,11,23,8,2,3,8,8
- dataends
- codesegment
- start:movax,data
- movds,ax
- movsi,0
- movax,0
- movcx,8
- s:cmpbyteptrds:[si],8
- jnenext
- incax
- next:incsi
- loops
- movax,4c00H
- int21H
- codeends
- endstart
10. DF 標(biāo)志位和串傳送指令
df=0 每次操作后si、di遞增;
df=1 每次操作后si、di遞減;
movsb
功能:將ds:si 指向的內(nèi)存單元中的字節(jié)送入es:di中,然后根據(jù)標(biāo)志寄存器df位的值,將si和di遞增或遞減1
相當(dāng)于:
(1)((es)*16+(di))=((ds)*16+(si))
(2)df=0則:(si)=(si)+1
(di)=(di)+1
df=1則:(si)=(si)-1
(di)=(di)-1
movsw
功能:于movsb相同,只是是傳送一個字,然后就是si和di是遞增或遞減2
指令cld,std
cld:將df設(shè)置為0
std:將df設(shè)置為1
rep指令
功能:根據(jù)cx的值重復(fù)執(zhí)行,后面的串指令。
格式:rep movsb
例子:復(fù)制data中的Welcome to masm!
- assumecs:code,ds:data
- datasegment
- dbWelcometomasm!
- db16dup(0)
- dataends
- codesegment
- start:movax,data
- movds,ax
- moves,ax
- movdi,16
- movsi,0
- movcx,16
- cld
- repmovsb
- movax,4c00h
- int21h
- codeends
- endstart
11. pushf和popf
pushf的功能是將標(biāo)志寄存器的值壓棧,而popf是從棧中彈出數(shù)據(jù),送入標(biāo)志寄存器中
評論