匯編語言之標(biāo)志寄存器
1、標(biāo)志寄存器
CPU內(nèi)部的寄存器中,有一種特殊的寄存器(對(duì)于不同的處理機(jī),個(gè)數(shù)和結(jié)構(gòu)都可能不同)具有以下3種作
用:
1. 用來存儲(chǔ)相關(guān)指令的某些執(zhí)行結(jié)果。
2. 用來為CPU執(zhí)行相關(guān)指令提供行為依據(jù)。
3. 用來控制CPU的相關(guān)工作方式。
這種特殊的寄存器在8086CPU中,被稱為標(biāo)志寄存器。8086CPU的寄存器,在前面已經(jīng)學(xué)過13個(gè)了,現(xiàn)
在學(xué)習(xí)最后一個(gè)寄存器FR-標(biāo)志寄存器。
FR與其它寄存器不一樣,其它寄存器是用來存放數(shù)據(jù)的,都是整個(gè)寄存器具有一個(gè)含義,而FR寄存器是按位
起作用的,也就是說它的每一位都有專門的含義,記錄特定的信息。
8086CPU的FR寄存器的結(jié)構(gòu)如下圖所示:
FR的第1、3、5、12、13、14、15位是空白位,在8086CPU中沒有使用,不具有任何意義,而第0、2、
4、6、7、8、9、10、11位都具有特殊的含義。
2、CF標(biāo)志
7.1 CF標(biāo)志
FR的第0位是CF,進(jìn)位標(biāo)志位。一般情況下,在進(jìn)行無符號(hào)數(shù)運(yùn)算的時(shí)候,它記錄了運(yùn)算結(jié)果的最高有效位
向更高位的進(jìn)位值,或從更高位的借位值。
對(duì)于位數(shù)為N的無符號(hào)數(shù)來說,其對(duì)應(yīng)的二進(jìn)制信息的最高位,即第N-1位,就是它的最高有效位,而假想
存在的第N位,就是相對(duì)于最高有效位的更高位,如下圖所示:
我們知道,當(dāng)兩個(gè)數(shù)據(jù)相加的時(shí)候,有可能產(chǎn)生從最高有效位向更高位的進(jìn)位,比如,兩個(gè)8位數(shù)據(jù):98H+
98H,將產(chǎn)生進(jìn)位,這個(gè)進(jìn)位值就用CF標(biāo)志位來保存。
比如,下面的指令:
Mov al, 98H
Add al, al
執(zhí)行后,計(jì)算結(jié)果為130H,al=30H,CF=1,CF記錄了從最高有效位向更高位的進(jìn)位值。
兩數(shù)相加,如果產(chǎn)生了進(jìn)位,則CF=1,如果沒有產(chǎn)生進(jìn)位,則CF=0。
當(dāng)兩個(gè)數(shù)據(jù)做減法的時(shí)候,有可能向更高位借位,比如,兩個(gè)8位數(shù)據(jù):97H-98H,將產(chǎn)生借位,借位后相
當(dāng)于計(jì)算197H-98H,而FR的CF標(biāo)志位也可以用來記錄這個(gè)借位值。
比如,下面的指令:
Mov al, 97H
Sub al, 98H
執(zhí)行后,計(jì)算結(jié)果為197H-98H=ffH,al=ffH,CF=1,CF記錄了向更高位的借位值。
兩數(shù)相減,如果產(chǎn)生借位,則CF=1,如果沒有產(chǎn)生借位,則CF=0。
3、adc指令
Adc是帶進(jìn)位加法指令,它利用了CF位上記錄的進(jìn)位值。
格式:adc 操作對(duì)象1,操作對(duì)象2
功能:操作對(duì)象1=操作對(duì)象1+操作對(duì)象2+CF
例1:mov ax, 1
Add ax, ax ;結(jié)果:ax=2,沒有產(chǎn)生進(jìn)位值,CF=0。
Adc ax, 3 ;結(jié)果:ax=ax+3+CF=2+3+0=5。
例2:mov al, 98H
Add al, al ;結(jié)果=130H,產(chǎn)生了進(jìn)位值,CF=1,al=30H。
Adc al, 3 ;結(jié)果:al=al+3+CF=30H+3+1=34H。
可以看出,adc指令比add指令多加了一個(gè)CF位的值,為什么要加上CF的值呢?CPU為什么要提供這樣一
條指令呢?
我們來看一下兩個(gè)數(shù)據(jù):0198H和0183H是如何相加的,見下圖:
可以看出,加法可以分兩步來進(jìn)行:1.低位相加(98+83)。2.高位相加再加上低位相加產(chǎn)生的進(jìn)位值(1+1
+1)??磥鞢PU提供adc指令的目的,就是來進(jìn)行加法的第二步運(yùn)算的。用adc指令和add指令相配合就可以
對(duì)更大的數(shù)據(jù)進(jìn)行加法運(yùn)算。
例3:計(jì)算1EF000H+201000H,結(jié)果放在ax(高16位)和bx(低16位)中。
因?yàn)閮蓚€(gè)數(shù)據(jù)的位數(shù)都大于16位,用add指令無法進(jìn)行計(jì)算,我們將計(jì)算分兩步進(jìn)行,先將低16位
(F000H和1000H)相加,然后將高16位(1EH和20H)和進(jìn)位值相加,代碼如下:
Mov ax, 1eH
Mov bx, f000H
Add bx, 1000H ;低16位相加,結(jié)果:f000H+1000H=10000H 產(chǎn)生了進(jìn)位值,CF=1,bx=0。
Adc ax, 20H ;高16位相加,結(jié)果:ax=ax+20H+CF=1eH+20H+1=3fH。
最終結(jié)果:ax=3fH,bx=0,1EF000H+201000H=3f0000H。
Adc指令執(zhí)行后,也可能產(chǎn)生進(jìn)位值,所以也會(huì)對(duì)CF位進(jìn)行設(shè)置,由于有這樣的功能,我們就可以對(duì)任意大
的數(shù)據(jù)進(jìn)行加法運(yùn)算。
例4:計(jì)算1EF0001000H+2010001EF0H,結(jié)果放在ax(最高16位),bx(次高16位),cx(低16位)
中。
計(jì)算分3步進(jìn)行:
1. 先將低16位(1000H和1EF0H)相加,完成后,CF記錄本次相加的進(jìn)位值。
2. 再將次高16位(F000H和1000H)和CF(來自低16位的進(jìn)位值)相加,完成后,CF記錄本次相加
的進(jìn)位值。
3.最后最高16位(1EH和20H)和CF(來自次高16位的進(jìn)位值)相加,完成后,CF記錄本次相加的進(jìn)位
值。
代碼如下:
Mov ax, 1eH
Mov bx, f000H
Mov cx, 1000H
Add cx, 1ef0H ;低16位相加,結(jié)果:1000H+1ef0H=2ef0H,沒有產(chǎn)生進(jìn)位值,CF=0,cx=2ef0H。
Adc bx, 1000H ;次高16位相加,結(jié)果:f000H+1000H+0=10000H,產(chǎn)生進(jìn)位值,CF=1,bx=0。
Adc ax, 20H ;最高16位相加,結(jié)果:ax=ax+20H+CF=1eH+20H+1=3fH,沒有產(chǎn)生進(jìn)位,CF=0。
最終結(jié)果:ax=3fH,bx=0,cx=2ef0H。1EF0001000H+2010001EF0H=3F00002EF0H。
4、sbb指令
Sbb是帶借位減法指令,它利用了CF位上記錄的借位值。
格式:sbb 操作對(duì)象1,操作對(duì)象2
功能:操作對(duì)象1=操作對(duì)象1-操作對(duì)象2-CF。
Sbb指令執(zhí)行后,將對(duì)CF進(jìn)行設(shè)置,利用sbb指令和sub指令配合使用可以對(duì)任意大的數(shù)據(jù)進(jìn)行減法運(yùn)算。
例1:計(jì)算3E1000H-202000H,結(jié)果放在ax(高16位),bx(低16位)。
計(jì)算分兩步進(jìn)行,先將低16位(1000H和2000H)相減,然后將高16位(3EH和20H)和借位值相減,
代碼如下:
Mov bx, 1000H
Mov ax, 3eH
Sub bx, 2000H ;低16位相減,結(jié)果:1000H-2000H=11000H-2000H=f000H,產(chǎn)生了借位值,
CF=1,bx=f000H。
Sbb ax, 20H ;高16位相減,結(jié)果:ax=ax-20H-CF=3eH-20H-1=1dH,沒有產(chǎn)生借位值,CF=0。
最終結(jié)果:ax=1dH,bx=f000H,3E1000H-202000H=1DF000H。
例2:計(jì)算6E4F0031C0H-1FA2002700H。結(jié)果放在ax(最高16位),bx(次高16位),cx(低16
位)。
計(jì)算分3步進(jìn)行:
1. 先將低16位(31C0H和2700H)相減,完成后,CF記錄本次相減的借位值。
2. 再將次高16位(4F00H和A200H)和CF(來自低16位的借位值)相減,完成后,CF記錄本次相減的
借位值。
3. 最后將最高16位(6EH和1FH)和CF(來自次高16位的借位值)相減,完成后,CF記錄本次相減的借
位值。
代碼如下:
Mov ax, 6eH
Mov bx, 4f00H
Mov cx, 31c0H
Sub cx, 2700H ;低16位相減,結(jié)果:31c0H-2700H=ac0H,沒有產(chǎn)生借位值,CF=0,cx=ac0H。
Sbb bx, a200H ;次高16位相減,結(jié)果:14f00H-a200H=ad00H,產(chǎn)生借位值,CF=1,bx=ad00H。
Sbb ax, 1fH ;最高16位相減,結(jié)果:ax=ax-1fH-CF=6eH-1fH-1=4eH,沒有產(chǎn)生借位值,CF=0。
最終結(jié)果:ax=4eH,bx=ad00H,cx=ac0H,6E4F0031C0H-1FA2002700H=4EAD000AC0H。
5、ZF標(biāo)志
FR的第6位是ZF,零標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果是否為0。如果(真),結(jié)果為0,那么ZF=1;
如果(假),結(jié)果非0,那么ZF=0。
對(duì)于ZF的值,我們可以這樣來看:在計(jì)算機(jī)中1表示邏輯真,表示肯定,所以當(dāng)結(jié)果為0的時(shí)候,ZF=1;在
計(jì)算機(jī)中0表示邏輯假,表示否定,所以當(dāng)結(jié)果不為0的時(shí)候,ZF=0。
下面的指令:
Mov ax, 5
Sub ax, ax
執(zhí)行后,結(jié)果為0,表示真,則ZF=1。
Mov ax, 5
Sub ax, 1
執(zhí)行后,結(jié)果不為0,表示假,則ZF=0。
6、cmp指令
Cmp是比較指令,它的功能相當(dāng)于sub指令,只是不保存結(jié)果。Cmp指令執(zhí)行后,將對(duì)標(biāo)志寄存器產(chǎn)生影
響,其它相關(guān)指令通過識(shí)別這些被影響的標(biāo)志位來得知比較結(jié)果。
指令格式:cmp 操作對(duì)象1,操作對(duì)象2
功能:計(jì)算操作對(duì)象1-操作對(duì)象2,但并不保存結(jié)果,僅僅根據(jù)計(jì)算結(jié)果對(duì)標(biāo)志寄存器的標(biāo)志位進(jìn)行設(shè)置。
Cmp指令執(zhí)行后,依據(jù)標(biāo)志位的值就可以看出比較結(jié)果。
比如,cmp ax, bx執(zhí)行后:
如果ZF=1,說明ax=bx,因?yàn)閍x-bx=0,那么ax必定等于bx。
如果ZF=0,說明ax≠bx,因?yàn)閍x-bx≠0,那么ax與bx必定不相等。
如果CF=1,說明ax<bx,因?yàn)閍x-bx產(chǎn)生了借位,那么ax必定小于bx。
如果CF=0,說明ax≥bx,因?yàn)閍x-bx沒有產(chǎn)生借位,那么ax必定大于或等于bx。
如果CF=0,并且ZF=0,說明ax>bx,因?yàn)閍x-bx沒有產(chǎn)生借位,并且ax-bx≠0,那么ax必定大于bx。
如果CF=1或ZF=1,說明ax≤bx,因?yàn)閍x-bx產(chǎn)生了借位,又或者ax-bx=0,那么ax必定小于或等于
Bx。
7、檢測(cè)比較結(jié)果的條件轉(zhuǎn)移指令
轉(zhuǎn)移指的是它能夠修改IP,而條件指的是它可以根據(jù)某種條件,決定是否修改IP,所有條件轉(zhuǎn)移指令都是短
轉(zhuǎn)移,轉(zhuǎn)移的位移范圍為﹣128~127。
大多數(shù)條件轉(zhuǎn)移指令都檢測(cè)標(biāo)志寄存器的相關(guān)標(biāo)志位,根據(jù)檢測(cè)的結(jié)果來決定是否修改IP,它們所檢測(cè)的標(biāo)
志位都是被cmp指令影響的那些表示比較結(jié)果的標(biāo)志位。
下面是常用的根據(jù)無符號(hào)數(shù)的比較結(jié)果進(jìn)行轉(zhuǎn)移的條件轉(zhuǎn)移指令。
指令 檢測(cè)的相關(guān)標(biāo)志位 與cmp配合使用的邏輯含義
Je 如果ZF=1則轉(zhuǎn)移 如果等于則轉(zhuǎn)移
Jne 如果ZF=0則轉(zhuǎn)移 如果不等于則轉(zhuǎn)移
Jb 如果CF=1則轉(zhuǎn)移 如果低于則轉(zhuǎn)移
Jnb 如果CF=0則轉(zhuǎn)移 如果不低于則轉(zhuǎn)移
Ja 如果CF=0且ZF=0則轉(zhuǎn)移 如果高于則轉(zhuǎn)移
Jna 如果CF=1或ZF=1則轉(zhuǎn)移 如果不高于則轉(zhuǎn)移
以上這些條件轉(zhuǎn)移指令是根據(jù)檢測(cè)相關(guān)的標(biāo)志位來決定是否轉(zhuǎn)移,比如:je是檢測(cè)ZF的值來決定是否轉(zhuǎn)移,
如果ZF=1則轉(zhuǎn)移,至于根據(jù)邏輯含義來決定是否轉(zhuǎn)移,則需要與cmp指令配合使用,這個(gè)在下一節(jié)會(huì)講到。
8、cmp與條件轉(zhuǎn)移指令配合使用
上一節(jié)介紹的條件轉(zhuǎn)移指令,所檢測(cè)的標(biāo)志位都是cmp指令進(jìn)行無符號(hào)數(shù)比較的時(shí)候,記錄比較結(jié)果的標(biāo)志
位,比如,je檢測(cè)ZF位,當(dāng)ZF=1時(shí)轉(zhuǎn)移,如果在je前面使用了cmp指令,那么je對(duì)ZF的檢測(cè),實(shí)際上是間
接地檢測(cè)cmp的比較結(jié)果是否為兩數(shù)相等。
請(qǐng)看下面一段代碼:
Cmp ax, bx
Je s
Add ax, bx
Jmp short ok
S:add ax, ax
Ok: …
上面的代碼執(zhí)行時(shí),如果ax=bx,則cmp ax, bx使ZF=1,而je檢測(cè)ZF是否為1,如果為1,則轉(zhuǎn)移到標(biāo)號(hào)
S處執(zhí)行指令add ax, ax,我們也可以這樣說,cmp比較ax, bx后所得到的相等的結(jié)果使得je指令進(jìn)行轉(zhuǎn)移,這
種說法很好地體現(xiàn)了je指令的邏輯含義,即“相等則轉(zhuǎn)移“。
“相等則轉(zhuǎn)移”這種邏輯含義是通過和cmp指令配合使用來體現(xiàn)的,我們用cmp指令與條件轉(zhuǎn)移指令配合使
用的時(shí)候,不必再考慮cmp指令對(duì)相關(guān)標(biāo)志位的影響和je等指令對(duì)相關(guān)標(biāo)志位的檢測(cè),因?yàn)橄嚓P(guān)的標(biāo)志位只是為
Cmp和je等指令傳遞比較結(jié)果,我們可以直接考慮cmp與je等指令配合使用時(shí),表現(xiàn)出來的邏輯含義。
請(qǐng)看下面的指令:
Cmp byte ptr [bx], 8 ;和8比較
Je 標(biāo)號(hào) ;如果等于則轉(zhuǎn)移
Cmp byte ptr [bx], 8 ;和8比較
Jne 標(biāo)號(hào) ;如果不等于則轉(zhuǎn)移
Cmp byte ptr [bx], 8 ;和8比較
Jb 標(biāo)號(hào) ;如果低于則轉(zhuǎn)移
Cmp byte ptr [bx], 8 ;和8比較
Jnb 標(biāo)號(hào) ;如果不低于則轉(zhuǎn)移
Cmp byte ptr [bx], 8 ;和8比較
Ja 標(biāo)號(hào) ;如果高于則轉(zhuǎn)移
Cmp byte ptr [bx], 8 ;和8比較
Jna 標(biāo)號(hào) ;如果不高于則轉(zhuǎn)移
上面的指令,用[bx]中的數(shù)值和8比較,“如果怎么怎么樣則轉(zhuǎn)移”,我們?cè)谛薷挠螒驎r(shí),可以根據(jù)這些邏輯含
義(即:如果怎么怎么樣則轉(zhuǎn)移),選擇合適的條件轉(zhuǎn)移指令。
9、其它標(biāo)志位
標(biāo)志寄存器的大部分標(biāo)志位,我們都不必深入地去學(xué)習(xí),因?yàn)檫@和修改游戲沒有多大關(guān)系,我們只需簡(jiǎn)單了解
一下即可,F(xiàn)R一共有9個(gè)標(biāo)志位,前面已學(xué)習(xí)了ZF和CF這兩個(gè)標(biāo)志位,現(xiàn)在講講余下的7個(gè)標(biāo)志位。
PF:奇偶標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果的所有二進(jìn)制位中1的個(gè)數(shù)是否為偶數(shù),如果(真),1的
個(gè)數(shù)為偶數(shù),PF=1,如果(假),1的個(gè)數(shù)為奇數(shù),PF=0。
比如,某些指令執(zhí)行后,其結(jié)果二進(jìn)制值為01001011,有4(偶數(shù))個(gè)1,則PF=1;某些指令執(zhí)行后,其
結(jié)果二進(jìn)制值為00001011,有3(奇數(shù))個(gè)1,則PF=0。
SF:符號(hào)標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果是否為負(fù),如果(真),結(jié)果為負(fù),SF=1,如果(假),結(jié)
果非負(fù),SF=0。
OF:溢出標(biāo)志位。一般情況下,OF記錄了有符號(hào)數(shù)運(yùn)算的結(jié)果是否發(fā)生了溢出,如果(真),發(fā)生了溢出,
OF=1,如果(假),沒有發(fā)生溢出,0F=0。
什么是溢出?在進(jìn)行有符號(hào)數(shù)運(yùn)算的時(shí)候,如結(jié)果超過了機(jī)器所能表示的范圍稱為溢出。那么,機(jī)器所能表示
的范圍是多少呢?對(duì)于8位的有符號(hào)數(shù)據(jù),機(jī)器所能表示的范圍就是﹣128~127;對(duì)于16位的有符號(hào)數(shù)據(jù),機(jī)器
所能表示的范圍就是﹣32768~32767。如果運(yùn)算結(jié)果超出了機(jī)器所能表達(dá)的范圍,將產(chǎn)生溢出。
比如,指令:
Mov al, 98
Add al, 99
執(zhí)行后,al=98+99=197,197超出了機(jī)器所能表示的8位有符號(hào)數(shù)的范圍:﹣128~127,所以產(chǎn)生了溢出。
DF:方向標(biāo)志位。在串處理指令中,控制每次操作后SI、DI的增減。
DF=0,每次操作后SI、DI遞增;DF=1,每次操作后SI、DI遞減。
DF標(biāo)志位與串傳送指令(movsb、movsw)有關(guān),而串傳送指令與游戲修改無關(guān),所以就不講解了。
TF:跟蹤標(biāo)志位。用于程序調(diào)試。
如果TF=1,則CPU處于單步執(zhí)行指令的工作方式,此時(shí),每執(zhí)行完一條指令,就顯示CPU各個(gè)寄存器的當(dāng)
前值及CPU將要執(zhí)行的下一條指令。如果TF=0,則處于連續(xù)工作模式。
AF:輔助進(jìn)位標(biāo)志位。在下列情況下,AF的值被設(shè)置為1,否則其值為0。
1. 在字操作時(shí),發(fā)生低字節(jié)向高字節(jié)進(jìn)位或借位時(shí)。
2. 在字節(jié)操作時(shí),發(fā)生低4位向高4位進(jìn)位或借位時(shí)。
IF:中斷允許標(biāo)志位。用來決定CPU是否響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請(qǐng)求,當(dāng)IF=1,響應(yīng)中斷
請(qǐng)求,當(dāng)IF=0,不響應(yīng)中斷請(qǐng)求。
10、lea和nop指令
Lea為有效地址傳送指令。
格式:lea 操作對(duì)象1,操作對(duì)象2
功能:將源操作數(shù)給出的有效地址傳送到指定的寄存器中。
說明:操作對(duì)象1為目的操作數(shù),可為任意一個(gè)16位的通用寄存器,操作對(duì)象2為源操作數(shù),可為地址表達(dá)
式。
比如,指令:
Lea ax, [217a]
執(zhí)行后,ax=217aH。
Lea ax, [bx+si+200]
執(zhí)行后,ax= bx+si+200H。
Nop為空操作指令。格式:nop。
功能:本指令不產(chǎn)生任何結(jié)果,僅消耗幾個(gè)時(shí)鐘周期的時(shí)間,接著執(zhí)行后續(xù)指令,常用于程序的延時(shí)等。
在修改游戲的時(shí)候,可用于鎖定某些數(shù)據(jù)的數(shù)值。
作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進(jìn)階人工智能(鏈接)