標(biāo)志寄存器

這就是計(jì)算機(jī)中的標(biāo)志寄存器,說到標(biāo)志我們就應(yīng)該想到flag,bool類型。而一個(gè)bool類型用1bit就可以表示了,所以我們談?wù)撨@個(gè)32位的標(biāo)志寄存器,更多的時(shí)候是討論其中的某一位。
比如0位,2位,4位,都是cpu中設(shè)定好的用途,就跟通用寄存器一樣,有自己的名字。比如C位,P位,O位。
進(jìn)位標(biāo)志位CF(carry flag)
如果運(yùn)算結(jié)果的最高位產(chǎn)生了一個(gè)進(jìn)位或借位,那么,其值為1,否則其值為0。
三個(gè)實(shí)驗(yàn):
mov al,0xff
add al,2 // c位變成1
mov al,0xfe // mov不是運(yùn)算所以C位不變
// C位手動(dòng)清零
add al,2 // c位又變成1
// C位手動(dòng)清零
mov ax,0xff
add ax,2 // c位已經(jīng)是0
// =========================重點(diǎn)
// 標(biāo)志寄存器在學(xué)習(xí)過程中,我們一定要明白數(shù)據(jù)的寬度
//【mov ax,0xff 】中,數(shù)據(jù)的寬度是16位,add之后,確實(shí)是進(jìn)位了,但不是最高位的進(jìn)位
補(bǔ)充:什么是運(yùn)算?
mov不算是運(yùn)算,其他的加減乘除異或等都是運(yùn)算
奇偶標(biāo)志位:PF(Parity Flag)
PF 反應(yīng)運(yùn)算結(jié)果中“1”的個(gè)數(shù)的奇偶性,如果1的個(gè)數(shù)是偶數(shù),則P位是1,如果1的個(gè)數(shù)是奇數(shù),則P位是0
實(shí)驗(yàn)
MOV AL,3 // 00001011 p位:0
add al,2 // 00001010 P位:1
輔助進(jìn)位標(biāo)志AF(Auxiliary Carry Flag)
在發(fā)生下列情況時(shí),輔助進(jìn)位標(biāo)志AF的值被置為1,否則其值為0:
(1)、在字節(jié)操作時(shí),發(fā)生低字節(jié)向高字節(jié)進(jìn)位或借位時(shí);
(2)、在字節(jié)操作時(shí),發(fā)生低4位向高4位進(jìn)位或借位時(shí)。
大白話說下,就是運(yùn)算時(shí),把位劃分成兩半,低位的一半的第一位如果向高位進(jìn)位(加)或者借位(減)時(shí),A位就是1
如下圖,就看突出的那一位
32位運(yùn)算: _ _ _ _ - _ _ _
16位運(yùn)算: _ _ - _
8位運(yùn)算: _ -
實(shí)驗(yàn):
// 第一組
MOV EAX,0x55EEFFFF
ADD EAX,2 // A位變1
// 第二組
MOV AX,5EFE
add ax,2 // A位又變1
// 第三組
MOV AL,4E
add al,2 // A位又變1
零標(biāo)志ZF(Zero Flag)
零標(biāo)志ZF用來反映運(yùn)算結(jié)果是否為0
如果運(yùn)算結(jié)果為0,則其值為1,否則其值為0。在判斷運(yùn)算結(jié)果是否為0時(shí),可使用此標(biāo)志位。
實(shí)驗(yàn)
XOR EAX,EAX // Z位:1
// 這句話的作用有兩個(gè)
// 1.將EAX的值變?yōu)?
// 2.將標(biāo)志位Z位置為1。如果[mov eax,0] 的話就沒有第二個(gè)作用了,mov就不是運(yùn)算
符號(hào)標(biāo)志SF(Sign Flag)
符號(hào)標(biāo)志SF用來反映運(yùn)算結(jié)果的符號(hào)位,它與運(yùn)算結(jié)果的最高位相同。
特別注意:這里的最高位說的是二進(jìn)制的最高位,所以只能是0或1
MOV AL,7F
ADD AL,2 // 1
溢出標(biāo)志OF(Overflow Flag)
溢出標(biāo)志OF用于反映有符號(hào)數(shù)加減運(yùn)算所得結(jié)果是否溢出。
如果運(yùn)算結(jié)果超過當(dāng)前運(yùn)算位數(shù)所能表示的范圍,則稱為溢出,OF的值被置為1,否則,OF的值被清為0。
最高位進(jìn)位(CF)和溢出(OF)的區(qū)別?
這里主要涉及到了無符號(hào)整數(shù)和有符號(hào)整數(shù)。計(jì)算機(jī)在存儲(chǔ)的時(shí)候,并不知道自己存儲(chǔ)的是有符號(hào)整數(shù)還是無符號(hào)整數(shù)。只有使用的人才知道,就是程序員嘍。
C位是做無符號(hào)運(yùn)算時(shí)該關(guān)注的
O位是做有符號(hào)運(yùn)算時(shí)該關(guān)注的
想知道現(xiàn)在計(jì)算的結(jié)果有沒有溢出,是看CF位還是OF位?
我要看那個(gè)取決于我做的是有符號(hào)還是無符號(hào)運(yùn)算。
如果你知道自己做的是無符號(hào)運(yùn)算,你只用看C位,不用管O位
如果你知道自己的做的是有符號(hào)運(yùn)算,只要看O位,不用管C位
好好看這個(gè)圖就什么都明白了


正數(shù)+負(fù)數(shù),一定在圈內(nèi),永遠(yuǎn)不會(huì)溢出
正數(shù)+正數(shù),如果結(jié)果為負(fù)數(shù)(超過7F內(nèi)),一定溢出。因?yàn)樵浇缌耍瑑蓚€(gè)正數(shù)相加不應(yīng)該是負(fù)數(shù)。
說結(jié)果之前,一定要指定到底是無符號(hào)運(yùn)算還是有符號(hào)預(yù)算。

自己這個(gè)分析判斷是錯(cuò)誤的,其實(shí)只要是圈上的點(diǎn)可以表示的,都沒有溢出,圈上的店不能表示的,就是溢出了。
只是有符號(hào)的話,只有右邊區(qū)域表示正數(shù),左邊區(qū)域表示負(fù)數(shù)
無符號(hào)的話,整個(gè)區(qū)域都可以表示
和標(biāo)志寄存器相關(guān)的指令
ADC指令:帶進(jìn)位加法

百度百科:
ADC 帶進(jìn)位的加法指令 ADC Reg/Mem, Reg/Mem/Imm 功能,將目的操作數(shù)和源操作數(shù)相加再加低位進(jìn)位,結(jié)果送入目的的地址 dst+src+cf->dst, 受影響的標(biāo)志位:AF、CF、OF、PF、SF和ZF,該指令的功能是把源操作數(shù)和進(jìn)位標(biāo)志位CF的值(0/1)一起加到目的操作數(shù)中。
實(shí)驗(yàn)
MOV AL,1
MOV CL,2
ADC AL,CL //按照我們正常的ADD指令,此時(shí)AL中應(yīng)該是3
// 但是ADC指令是帶進(jìn)位的加法,它會(huì)把c位中的值也給加上。
// 如果此時(shí)cf中的值是1,那結(jié)果:AL中的值是4,cf的值:0
注意事項(xiàng):1.兩邊
SBB指令:帶借位減法

百度百科的解釋很明確
SBB:帶借位減法, 格式:SBB DST,SRC, 執(zhí)行的操作:(DST)←(DST)-(SRC)-CF,其中CF為進(jìn)位的值。 SBB Compents :他們組成了Application .他們以何種方式組合是由SLEE來確定的。
實(shí)驗(yàn)
MOV AL,3
MOV CL,1
SBB AL,CL
// 分兩種情況:
// 1. 如果cf是0,那么結(jié)果和我們預(yù)想的一樣,2
// 2. 如果cf是1,那么結(jié)果還會(huì)減1,結(jié)果al變?yōu)?了
XCHG指令:交換數(shù)據(jù)

百度百科
交換指令XCHG是兩個(gè)寄存器,寄存器和內(nèi)存變量之間內(nèi)容的交換指令,兩個(gè)操作數(shù)的數(shù)據(jù)類型要相同,可以是一個(gè)字節(jié),也可以是一個(gè)字,也可以是雙字
說明什么?
我們交換的是兩個(gè)容器,不能是立即數(shù)
而且交換的兩個(gè)容器不能都是內(nèi)存
// 實(shí)驗(yàn):
MOV AL,1
MOV CL,3
XCHG AL,CL // AL變成3,CL變成了1
XCHG DWORD PTR DS:[0X0019FF74],EAX
MOVS指令:移動(dòng)數(shù)據(jù)

看了一下通用寄存器中EDI和ESI的分工:

再回顧一下通用寄存器的劃分:
https://xuxiaofeng.gitlab.io/2018/12/12/study-%E7%BC%96%E7%A8%8B%E8%BE%BE%E4%BA%BA-%E6%BB%B4%E6%B0%B4%E9%80%86%E5%90%913%E6%9C%9F%E5%AD%A6%E4%B9%A0-2018-12-12-%E8%BF%9B%E4%B8%80%E6%AD%A5%E5%AD%A6%E4%B9%A0%E5%AF%84%E5%AD%98%E5%99%A8/

現(xiàn)在我們來解釋MOVS指令
movs指令是用來復(fù)制一個(gè)數(shù)據(jù)項(xiàng)(字節(jié),字或雙字)從源字符串到目標(biāo)字符串。原字符串又ESI/SI/DH 指出,目標(biāo)字符串又EDI/DI/BH指出。(具體又那個(gè)指出,我們需要看使用時(shí)定義的單位)
這里還有一段解釋:
MOVS指令可以把由(SI)指向的數(shù)據(jù)段中的一個(gè)字(或字節(jié))傳送到由(DI)指向的附加段中的一個(gè)字(或字節(jié))中去,同時(shí)根據(jù)方向標(biāo)志(df標(biāo)志寄存器)及數(shù)據(jù)格式(字 或字節(jié))對(duì)SI和DI進(jìn)行修改
在執(zhí)行該指令前,應(yīng)該先做好以下 準(zhǔn)備工作:
1) 把存放于數(shù)據(jù)段中的源串首地址(如反向傳送則應(yīng)是末地址)放入SI寄存器中;
2) 把將要存放數(shù)據(jù)串的附加段中的目的串首地址(或反向傳送時(shí)的末地址)放入DI寄存器中;
3) 建立方向標(biāo)志。
實(shí)驗(yàn)
首先說明一下,我們之前碰到內(nèi)存的時(shí)候,我們總是這樣表示DS:[],沒錯(cuò)。但是碰到EDI表示內(nèi)存地址單元時(shí),我們應(yīng)該這樣ES:[],所以往下,我們會(huì)經(jīng)??吹竭@樣的字符:ES:[EDI] (這里涉及到段、頁(yè)的概念)
1.直接輸入movs,點(diǎn)擊確定,編輯器就會(huì)自動(dòng)給我們生成下面的額語句
充分說明了這個(gè)指令是針對(duì)EDI和ESI的
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
mov edi,0019ff88
mov esi,0019ff80
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
結(jié)果
edi:0019ff8c
esi:0019ff84
并且剛才edi對(duì)應(yīng)內(nèi)存編號(hào)中的值和dsi對(duì)應(yīng)內(nèi)存編號(hào)中的值確實(shí)做了交換
我們發(fā)現(xiàn)EDI和ESI中的值都+4 了。這是有D位(df標(biāo)志寄存器決定的)
所以這個(gè)MOVS指令有兩個(gè)主要影響,一是真的交換了寄存器對(duì)應(yīng)內(nèi)存地址單元中的值,二是根據(jù)DF標(biāo)志寄存器中的值,讓ESI和EDI都進(jìn)行一些位移。
STOS指令:講Al/AX/EAX的值存儲(chǔ)到[EDI]指定的內(nèi)存單元
到底是復(fù)制AL還是AX還是EAX,是又我們指定的內(nèi)存寬度決定的
。復(fù)制完畢后,EDI的變化方向是由我們的D位(df標(biāo)志寄存器)決定的。

// 實(shí)驗(yàn)
mov eax,12345678
mov edi,0019ff88
直接數(shù)據(jù)stos,確定酒水彈出下面的值
STOS DWORD PTR ES:[EDI]
運(yùn)行結(jié)果(D位此時(shí)是0)
DEI:0019FF8C
內(nèi)存單元0019FF88中的值:12345678
REP指令:按計(jì)數(shù)寄存器 (ECX) 中指定的次數(shù)重復(fù)執(zhí)行字符串指令
這里有一個(gè)把movs和rep指令糅合在一起的解釋
MOVS指令可以把由(SI)指向的數(shù)據(jù)段中的一個(gè)字(或字節(jié))傳送到由(DI)指向的附加段中的一個(gè)字(或字節(jié))中去,同時(shí)根據(jù)方向標(biāo)志及數(shù)據(jù)格式(字 或字節(jié))對(duì)SI和DI進(jìn)行修改。當(dāng)該指令與前綴REP聯(lián)用時(shí),則可將數(shù)據(jù)段中的整串?dāng)?shù)據(jù)傳送到附加段中去。這里源串必須在數(shù)據(jù)段中,目的串必須在附加段 中,但源串允許使用段跨越前綴來修改。在與REP聯(lián)用時(shí)還必須先把數(shù)據(jù)串的長(zhǎng)度送到CX寄存器中,以便控制指令結(jié)束。因此在執(zhí)行該指令前,應(yīng)該先做好以下 準(zhǔn)備工作:
1) 把存放于數(shù)據(jù)段中的源串首地址(如反向傳送則應(yīng)是末地址)放入SI寄存器中;
2) 把將要存放數(shù)據(jù)串的附加段中的目的串首地址(或反向傳送時(shí)的末地址)放入DI寄存器中;
3) 把數(shù)據(jù)串長(zhǎng)度放入CX寄存器;
4) 建立方向標(biāo)志。
在完成這些準(zhǔn)備工作后就可使用串指令傳送信息了
MOV ECX,10
REP MOVSD
REP STOSD