ARM匯編之解惑條件標(biāo)志,條件碼,條件執(zhí)行

什么是條件執(zhí)行(Conditional execution),它的機(jī)理是,根據(jù)運(yùn)算結(jié)果更新的條件標(biāo)志(condition flags),來(lái)判斷指令的條件碼(Condition code)是否符合條件,符合條件就執(zhí)行,不符合條件則不執(zhí)行。

A32/T32指令可以根據(jù)之前匯編指令更新的條件標(biāo)志,來(lái)帶條件的執(zhí)行當(dāng)前的匯編指令。為了讓匯編指令帶條件的執(zhí)行,需要為匯編指令增加條件碼后綴,這樣就可以讓處理器基于條件標(biāo)志來(lái)測(cè)試是否需要執(zhí)行該指令,如果條件測(cè)試不符,指令不會(huì)被執(zhí)行,也不會(huì)影響其他任何標(biāo)志,更不會(huì)產(chǎn)生異常,但是由于仍然占用了一個(gè)流水線空間,會(huì)消耗一個(gè)指令周期,除此之外什么也不會(huì)發(fā)生。

  • 幾乎所有A32的指令都可以基于APSR中的條件標(biāo)志,進(jìn)行帶條件判斷的執(zhí)行。
  • 而T32的話只支持部分 指令帶條件的執(zhí)行,分支指令,CBZ(零條件分支)/CBNZ(非零條件分支)——根據(jù)寄存器結(jié)果是否為零在同一個(gè)執(zhí)行狀態(tài)下進(jìn)行短距離(0~126字節(jié))跳轉(zhuǎn),IT(If-Then,16位指令)。
  • 同樣在A64里面也只有少數(shù)指令可以真正的有條件執(zhí)行(也就是說(shuō),要是條件測(cè)試不符,PC值仍然是往前增加的,除此沒(méi)有別的影響),這些指令包括 B.EQ,CBNZ,CBZ,TBNZ,TBZ。

條件標(biāo)志(condition flags)

總共有四個(gè)條件標(biāo)志 N, Z, C, V,A32/T32中可存儲(chǔ)更新到APSR寄存器最高的4個(gè)位置。大致示意圖如下:


image.png

大部分的A32匯編指令編碼中也會(huì)包含這四個(gè)位,而16位的T32指令大部分沒(méi)有這些,所以不能帶條件的執(zhí)行,16位的指令編碼帶有的信息有限通常不會(huì)包含這四個(gè)位。

下面我們來(lái)說(shuō)說(shuō),什么情況下這四個(gè)位會(huì)被置位/清除

條件標(biāo)志 置位/清除
N 當(dāng)運(yùn)算的結(jié)果為負(fù)數(shù)的話置位,其他情況清0
Z 當(dāng)運(yùn)算的結(jié)果為0的話置位,其他情況清0
C 當(dāng)運(yùn)算的結(jié)果產(chǎn)生進(jìn)位或者減法運(yùn)算沒(méi)有借位的話置位,其他情況清0
V 當(dāng)運(yùn)算的結(jié)果產(chǎn)生溢出的話置位,其他情況清0
  • 可能看完上面的表還是有點(diǎn)不明白,下面繼續(xù)進(jìn)行補(bǔ)充說(shuō)明。最復(fù)雜的是C位了(這也是今年大家都想要的一個(gè)位:)),那就先講一下C位,C位會(huì)在下面四種情況下被置位:

    • 無(wú)符號(hào)的(unsigned)加法運(yùn)算(包括比較指令CMN)如果產(chǎn)生進(jìn)位,C置位。

    • 無(wú)符號(hào)的(unsigned)減法運(yùn)算(包括比較指令CMP)如果沒(méi)有借位(減完結(jié)果是正的),C置位。

    • 移位操作也會(huì)影響C位(可以參考我之前文章中對(duì)移位操作介紹,ARM匯編指令中靈活的第二操作數(shù)),C的值是最后一個(gè)被移位器移出的位值,當(dāng)然這個(gè)被移出的位值如果為1那么C值就為1

    • 除了上面3種情況,C位通常是不會(huì)被改變的,但也有特殊指令會(huì)造成C位改變,這個(gè)如果自己在編程時(shí)會(huì)用到C位最好參考一下匯編指令手冊(cè),確認(rèn)一下對(duì)應(yīng)的指令是否對(duì)C位有特殊影響。

例子1

ldr r1,=0xffffffff
ldr r2,=0x2
adds r3,r1,r2

例子2

mov r2,#3
mov r1,#1
subs r3,r2,r1;r3 = r2 - r1
  • 在來(lái)說(shuō)一下V位,這個(gè)位是針對(duì)有符號(hào)的加法/減法及比較的,溢出,何為溢出呢,如果運(yùn)算的結(jié)果大于等于2的31次方,或者小于負(fù)的2的31次方則V置位

例子:

ldr r1,=0x7fffffff
ldr r2,=0x2
adds r3,r1,r2
  • N位是用來(lái)檢測(cè)運(yùn)算結(jié)果是否為負(fù)數(shù)時(shí)比較有用。什么是負(fù)數(shù)呢,在計(jì)算機(jī)系統(tǒng),負(fù)數(shù)通常用二進(jìn)制的補(bǔ)碼來(lái)表示,如果最高有效位被置位,則該二進(jìn)制補(bǔ)碼為負(fù)數(shù)。也就是說(shuō)運(yùn)算結(jié)果最高位為1那么N位就置位。

例子:

mov r1,#-1
mov r2,#-2
adds r3,r1,r2
  • Z位是最好理解的,只有運(yùn)算的結(jié)果所有的位都為0則,Z置位。

例子:

mov r1,#0
mov r2,#0
adds r3,r1,r2

更新條件標(biāo)志

  • 在A32/T32中條件標(biāo)志大部分情況下,不會(huì)自動(dòng)更新到APSR中,只有你的指令明確的告訴它要更新它才會(huì)去更新,比如你在匯編指令中使用 S 后綴明確告訴它要去更新 APSR中的這些位。如下面的這條指令語(yǔ)法格式,你用ADDS就會(huì)去更新條件標(biāo)志,用ADD就不會(huì)去更新。
    ADD{S}{cond} {Rd}, Rn, Operand2
  • 至于四個(gè)標(biāo)志位被更新了幾個(gè),這個(gè)跟具體的指令有關(guān),有的4位都更新了,有的只更新了1位或者都不更新。為什么會(huì)更新多位,因?yàn)橛?jì)算機(jī)并不知道你操作的是有符號(hào)數(shù)還是無(wú)符號(hào)數(shù),是正數(shù)還是負(fù)數(shù),它只能傻傻的把所有可能全部給你列出來(lái),所以你要對(duì)你寫(xiě)的程序負(fù)責(zé),你要清楚你在做什么,你是做有符號(hào)的操作,還是無(wú)符號(hào)的操作,還是對(duì)正/負(fù)數(shù)操作,并以此選擇你想要測(cè)試的條件標(biāo)志位,來(lái)看操作結(jié)果是否符合預(yù)期,簡(jiǎn)單說(shuō)就是你要什么,你就要去判斷什么。

例子:

ldr r1,=0x7fffffff
ldr r2,=0x2
adds r3,r1,r2
bvc stop
nop
nop
nop

stop b stop

下圖是上面程序運(yùn)行之后,條件標(biāo)志更新結(jié)果:

image.png
  • 因?yàn)橛?jì)算機(jī)不知道你要的是什么,所有它把所有情況都考慮進(jìn)去了
    • 如果r1,r2是無(wú)符號(hào)數(shù),顯然加法結(jié)果沒(méi)有溢出因此C位為0
    • 如果r1,r2是有符號(hào)數(shù),加法結(jié)果超過(guò)了有符號(hào)數(shù)的上限而溢出因此V位為1
    • 同時(shí)r3 = r1 + r3 = 0x80000001,最高位是1,因此N位也為1
    • 計(jì)算的結(jié)果顯然并不為0,因此Z為為0。

因此接下來(lái)你要用合適的條件碼來(lái)對(duì)操作結(jié)果進(jìn)行判斷,比如你明確r1,r2是有符號(hào)數(shù),你要判斷有符號(hào)的加法是否溢出,你就需要對(duì)V位進(jìn)行判斷,如例子中的vc條件碼。

備注:CMP, CMN,TEQ, TST這幾條指令總是會(huì)更新條件標(biāo)志位。他們沒(méi)有S后綴的格式。如果帶條件執(zhí)行的指令沒(méi)有被執(zhí)行,它不會(huì)影響條件標(biāo)志。

  • A64中這四個(gè)條件標(biāo)志是放在NZCV系統(tǒng)寄存器的,除了CMP,CMN, CCMP, CCMN, TST這幾條總是會(huì)更新條件標(biāo)志的,其他指令需要更新條件標(biāo)志同樣需要帶S的后綴。

條件碼(Condition code)

  • 條件碼由兩個(gè)字母組成,在A32/A64中支持條件碼后綴的匯編指令中通常會(huì)有一個(gè) {cond}的語(yǔ)法選項(xiàng),比如下面ADD的語(yǔ)法格式
    ADD{S}{cond} {Rd}, Rn, Operand2
  • 對(duì)于T32指令,條件碼在前面的IT指令中編碼。

所有支持的條件碼(下圖第一列)及含義如下圖所示

image.png

例子:

    mov r2,#6
    ldr r1,=0x7fffffff
    subs r3,r2,r1;r3 = r2 - r1
    bgt stop
    nop
    nop
    nop 
stop b stop

比較指令

  • 上面提到的CMP, CMN,TEQ, TST這幾條指令,總是會(huì)更新條件標(biāo)志位,但運(yùn)算結(jié)果總是被扔掉,不會(huì)進(jìn)行保存。

他們的語(yǔ)法格式如下

CMP{cond} Rn, Operand2;Rn - Operand2 操作類(lèi)似SUBS(除了扔掉運(yùn)算結(jié)果)
CMN{cond} Rn, Operand2;Rn + Operand2 操作類(lèi)似ADDS(除了扔掉運(yùn)算結(jié)果)
TEQ{cond} Rn, Operand2;Rn EOR Operand2  操作類(lèi)似EORS(除了扔掉運(yùn)算結(jié)果)
TST{cond} Rn, Operand2;Rn AND Operand2  操作類(lèi)似ANDS(除了扔掉運(yùn)算結(jié)果)

備注:對(duì)TEQ和TST來(lái)說(shuō)不會(huì)影響到V標(biāo)志,N位和Z位會(huì)根據(jù)操作結(jié)果會(huì)被更新,Operand2移位操作也可能會(huì)影響到C位。而CMP和CMN則根據(jù)運(yùn)算結(jié)果都有可能會(huì)被影響到。

例子:

    mov r1,#-1
    mov r2,#0
    tst r1,r2
    beq stop
    nop
    nop
    nop

stop b stop

為什么需要條件執(zhí)行

  • 因?yàn)闂l件執(zhí)行比條件分支效率更高。在沒(méi)有分支預(yù)測(cè)(至于什么是分支預(yù)測(cè),有興趣的同學(xué)可以參考計(jì)算機(jī)原理的相關(guān)書(shū)籍,有詳細(xì)介紹)的ARM處理器上如果發(fā)生分支跳轉(zhuǎn),需要重填三個(gè)機(jī)器指令周期的流水線,當(dāng)然如果有分支預(yù)測(cè)功能的ARM處理器在預(yù)測(cè)失敗時(shí),也是需要重填的。
    下面是從ARM手冊(cè)摘出來(lái)的一個(gè)例子:

C語(yǔ)言描述的算法如下:

int gcd(int a, int b)
{
    while (a != b)
      {
        if (a > b)
            a = a - b;
        else
            b = b - a;
      }
    return a;
}

如果用條件分支實(shí)現(xiàn),代碼如下:

gcd     CMP      r0, r1
        BEQ      end
        BLT      less
        SUBS     r0, r0, r1  ; could be SUB r0, r0, r1 for A32
        B        gcd
less
        SUBS     r1, r1, r0  ; could be SUB r1, r1, r0 for A32
        B        gcd
end

如果用帶條件指令的條件執(zhí)行,代碼如下:

gcd
        CMP      r0, r1
        SUBGT    r0, r0, r1
        SUBLE    r1, r1, r0
        BNE      gcd

跟用分支執(zhí)行的比較,該代碼長(zhǎng)度更小,而且執(zhí)行的也更快。


參考資料

【1】DUI0801I_armasm_user_guide
【2】ARM Development Tools
【3】ARM Assembly Language_ Fundamentals and Techniques (2nd ed.)
【4】DDI0487C_a_armv8_arm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容