制作網(wǎng)站的知識(shí)免費(fèi)推廣方式有哪些
本節(jié)解決了x86-64如何實(shí)現(xiàn)條件語句、循環(huán)語句和分支語句的問題
條件碼
除了整數(shù)寄存器外,cpu還維護(hù)著一組單個(gè)位的條件碼寄存器,用來描述最近的算數(shù)和邏輯運(yùn)算的某些屬性??蓹z測這些寄存器來執(zhí)行條件分支指令。
CF(Carry Flag):進(jìn)位標(biāo)志。最近的算術(shù)或邏輯運(yùn)算使得最高位產(chǎn)生了進(jìn)位??蓹z查無符號數(shù)操作的溢出。
ZF(Zero Flag):零標(biāo)志。最近的算術(shù)或邏輯運(yùn)算結(jié)果為0。
SF(Sign Flag):符號標(biāo)志。最近的算術(shù)或邏輯運(yùn)算結(jié)果為負(fù)數(shù)。
OF(Overflow Flag):溢出標(biāo)志。最近的算術(shù)或邏輯運(yùn)算導(dǎo)致補(bǔ)碼溢出——正溢出或負(fù)溢出。
這里指出,leaq不會(huì)改變?nèi)魏螚l件碼,因?yàn)槭潜挥脕磉M(jìn)行地址計(jì)算的。對于邏輯操作,例如XOR,進(jìn)位和溢出標(biāo)志會(huì)設(shè)置為0。對于移位操作,進(jìn)位標(biāo)志將設(shè)置為最后一個(gè)被移出的位,溢出標(biāo)志設(shè)為0。INC和DEC指令會(huì)設(shè)置溢出和零標(biāo)志,但不會(huì)改變進(jìn)位標(biāo)志。
除了基本的算術(shù)和邏輯指令會(huì)設(shè)置條件碼之外,還有兩類指令(8,16,32,64位形式)會(huì)設(shè)置條件碼。
CMP指令行為與SUB指令一致,只是不會(huì)改變目的寄存器。
TEST指令與AND指令一致,只是不會(huì)改變目的寄存器的值。
訪問條件碼
通常不會(huì)直接讀取條件碼。常用方法有三種:(1)根據(jù)條件碼的某種組合,將一個(gè)字節(jié)設(shè)置為0或者1。(2)可以條件跳轉(zhuǎn)到程序的某個(gè)其他的部分。(3)可以有條件的傳輸數(shù)據(jù)。
對于第一種情況,我們用SET這類指令設(shè)置某個(gè)字節(jié)為1或0。SET根據(jù)某些條件碼的算術(shù)或邏輯組合,將寄存器的某個(gè)低位字節(jié)或某個(gè)一個(gè)字節(jié)的內(nèi)存位置置為1或0。
下圖是SET指令
需要注意SET指令在大小比較時(shí)有符號數(shù)和無符號數(shù)是不同的指令。
舉個(gè)例子分析下
我們來分析setl(有符號小于)具體是在那幾個(gè)條件碼的何種組合下進(jìn)行工作的
cmpq獲得a - b,這里在運(yùn)算時(shí)可能會(huì)有如下幾種情況
(1)未溢出,這時(shí)OF(溢出標(biāo)志位)為0,則a - b的結(jié)果小于0那么a < b,根據(jù)a - b的結(jié)果小于0,SF被設(shè)為1。
(2)溢出,OF = 1,cmpq的結(jié)果由兩種情況:小于零,說明a - b > 0,只有這樣才會(huì)使得a和b進(jìn)行補(bǔ)碼減法后負(fù)溢出;大于零,說明a - b < 0,只有這樣才會(huì)使得a和b進(jìn)行補(bǔ)碼減法后正溢出。(等于零不會(huì)溢出)這就可以看出只有cmpq運(yùn)算結(jié)果是正數(shù)才能說明a < b。于是SF = 0。
可以看出 OF和SF異或的結(jié)果是setl判斷的標(biāo)準(zhǔn),若異或結(jié)果為1,說明a < b,%al被設(shè)為1;否則為0。
SET指令會(huì)區(qū)分有符號值和無符號值,這在匯編語言中并不常見,大多數(shù)情況,有符號數(shù)和無符號數(shù)都使用一樣的指令,因?yàn)樵S多算術(shù)運(yùn)算對無符號數(shù)和補(bǔ)碼都有一樣的位級行為。部分情況需要使用不同的指令,例如,右移、除法、乘法。