匯編語言之標(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)階人工智能(鏈接)