高效的C編程之:布爾表達(dá)式
通常,布爾表達(dá)式被用來檢測某個數(shù)值是否在特定的范圍內(nèi)。例如,在圖形窗口處理程序中,常使用布爾表達(dá)式判斷屏幕中一個點(diǎn)是否在當(dāng)前活動窗口范圍內(nèi)。
下面的程序使用結(jié)構(gòu)體定義點(diǎn)坐標(biāo)并計(jì)算坐標(biāo)的當(dāng)前位置。
boolPointInRect1(Pointp,Rectangle*r)
{return(p.x>=r->xmin&&p.x<r->xmax&&
p.y>=r->ymin&&p.y<r->ymax);
}
上面的功能函數(shù),被編譯為下面的指令序列。
PointInRect1
LDRa4,[a3,#0]
CMPa1,a4
BLT|L000034.J5.PointInRect1|
LDRa4,[a3,#4]
CMPa4,a1
BLE|L000034.J5.PointInRect1|
LDRa1,[a3,#8]
CMPa2,a1
BLT|L000034.J5.PointInRect1|
LDRa1,[a3,#&c]!
CMPa2,a1
MOVLTa1,#1
MOVLTpc,lr
|L000034.J5.PointInRect1|
MOVa1,#0
MOVpc,lr
但上面的代碼并不是最精簡的。編譯器對(x>=min&&x<max)形式的布爾表達(dá)式的處理過程比較復(fù)雜。它將以(unsigned)(x-min)<(max-min)形式實(shí)現(xiàn)布爾操作。所有對于上面范圍判斷的代碼,建議將函數(shù)寫成如下形式。
boolPointInRect2(Pointp,Rectangle*r)
{return((unsigned)(p.x-r->xmin)<r->xmax&&
(unsigned)(p.y-r->ymin)<r->ymax);
}
這樣編譯出的匯編指令序列如下所示。
PointInRect2
LDRa4,[a3,#0]
SUBa1,a1,a4
LDRa4,[a3,#4]
CMPa1,a4
LDRCCa1,[a3,#8]
SUBCCa1,a2,a1
LDRCCa2,[a3,#&c]!
CMPCCa1,a2
MOVCSa1,#0
MOVCCa1,#1
MOVpc,lr
14.4.2和零的比較操作比較指令(CMP)將設(shè)置程序狀態(tài)字的條件標(biāo)志位。另外,基本的算術(shù)指令也可以設(shè)置條件標(biāo)志位,如使用指令MOVS、ADDS等。如果程序中的算術(shù)指令的執(zhí)行目的是為了將計(jì)算結(jié)果和零比較,那么就可以直接使用帶標(biāo)志擴(kuò)展的基本算術(shù)指令。如下面的兩條語句:
ADDR0,R0,R1
CMPR0,#0
可以合并為一條帶符號擴(kuò)展的加法指令:
ADDSR0,R0,R1
事實(shí)上,C語言中的和零相關(guān)的關(guān)系操作都可以利用狀態(tài)標(biāo)志寄存器的N位和Z位。如:x<0,x>=0,x=0,x!=0,和無符號操作x=0,x!=0(orx>0)。
對于每一條C語言中的關(guān)系操作,匯編器都將產(chǎn)生一條比較指令。如果關(guān)系操作和零相關(guān),則可以將產(chǎn)生的比較指令移除。
下面是C語言中的關(guān)系操作被編譯的例子。
C源文件如下所示。
intg(intx,inty)
{
if((x+y)<0)
return1;
else
return0;
}
編譯后的結(jié)果如下。
g
ADDSa1,a1,a2
MOVPLa1,#0
MOVMIa1,#1
MOVpc,lr
所以,在使用C語言編程時,關(guān)系操作最好轉(zhuǎn)換成和零相關(guān)的,這樣既可以減少代碼密度,也可以提高程序的執(zhí)行效率。
C語言中,沒有和程序狀態(tài)寄存器的C位和V位直接相關(guān)的指令,所以要在程序中檢測這些標(biāo)志,只能使用內(nèi)嵌匯編。但C編譯器支持無符號溢出操作,下面的例子顯示了在有溢出操作時,編譯器對程序的處理。
C源代碼如下所示。
intsum(intx,inty)
{
intres;
res=x+y;
if((unsigned)res<(unsigned)x)/*判斷進(jìn)位標(biāo)志是否進(jìn)位*/
res++;
returnres;
}
編譯的匯編文件如下所示。
sum
ADDSa2,a1,a2
ADCa2,a2,#0
MOVa1,a2
MOVpc,lr