3.6控制
3.6.1條件碼
l 除整數寄存器外,CPU還有一級單位個條件碼,其中最有用的條件碼是:
CF:進位標誌,可以用來檢測無符號操作數溢出
ZF:零標誌
SF:符號標誌,最近的操作得到的結果爲負數
OF:溢出標誌,最近操作導致一個二進制實在溢出——正溢出或負溢出
例如,addl指令完成簮於C表達式t=a+b的功能,這裏變量a、b、t都是整型,條件碼的設置如下:
CF:(unsigned t)<(unsigned a) 無符號溢出
ZF:(t==0 ) 零
SF:(t<0) 負數
OF:(a<0 == b<0) && (t<0 != a<0) 有符號溢出
l Leal指令不改變任何條件碼,因爲它是用來做地址計算的,另外,一、二元操作指令都會設置條件碼;對於另外一些指令:cmp test只設置條件碼,而不改變任何其他寄存器
3.6.2訪問條件碼
訪問條件碼的方式最常用的有兩種,並不是直接讀,而是根據條件碼的某個組合,設置一個整數寄存器或是執行一條件分支指令。特別記住的是set指令族,它和前面mov族一樣,有很多兄弟:
(桔紅色和天藍色分別用於有符號和無符號)
sete D D=ZF
setne D D=~ZF
sets(負數) D D=SF
setns D D=~SF
有符號數的比較,如cmp $a,$b ,是利用a-b然後得出結果,由於是有符號數,因此會有四種情況出現:1、無溢出,結果爲正或0,2、無溢出,結果爲負或0,3、有溢出,結果是一個很大的正數,4、有溢出,結果是一個很小的負數;因此可以看出這一個操作將涉及三個標誌:有符號溢出OF、0標誌ZF、符號標誌SF
setg D D=~(SF|OF)&~ZF
setge D D=~(SF^|OF)
setl D D=SF^|OF
setle D D=(SF^OF)|ZF
無符號比較,由於沒有符號,因此在其合理表示範圍內也不存在負數(因此也就不涉及SF了),所以其結果只有兩種:正數或負數(這裏的負數即是溢出了),當得到的結果差爲負數時,cmp指令會設置進位標誌,用以標識無符號數的溢出,因此會使用進位標誌CF和零標誌OF組合表示最終比較結果
seta(超過) D D=~CF&~ZF
setae D D=~CF
setb(低於) D D=CF
setbe D D=CF|ZF
3.6.3跳轉指令和它們的編碼
l 跳轉指令有直接和間接跳轉,分別對應於jmp label、jmp *Operand。直接跳轉表示跳轉目標是作爲指令的一部分編碼的;間接跳轉,指跳轉目標是從寄存器或存儲器位置中讀出的。條件指令只能是直接跳轉。
l Jmp指令也有很多兄弟,其兄弟形式如set,例如:je jne ……
l 跳轉指令有幾種編碼,但是常用的是PC相關的代碼,彙編時,它們會將目標指令與跳轉指令之後的指令地址差爲作編碼。如下彙編代碼:
8:7e 11 (jmp 指令)
a: 8d b6 00 00 00 00(緊隨jmp指令的後一條指令)
……
可以看到地址0x8中,0x7e代表jmp指令,那麼上面的彙編代碼告訴我們的信息便是jmp將要跳轉的地址爲0x11 + 0xa = 0x1b。所以可以看到,所謂的PC相關(PC是程序計數器,可以得到下一條將執行的指令,這裏溫習一下,有助於理解“PC相關”這個概念)工作方式是指,彙編時首先得到jmp將要跳轉的目的地址,然後用目的地址減去jmp指令的下一條指令(這就是爲什麼它和PC有關了)的地址,這個差就做爲jmp指令的參數。