arm的常數表示式
如果說intel指令中的立即數,相信大家都很熟悉。類似的,arm指令中的「立即數」就是常數表示式。之所以稱為常數表示式,而不稱為立即數是有原因的。
intel
指令屬於cisc指令集,指令是不定長的,因此可以將任意32位立即數編碼到指令內。
arm指令屬於risc指令集,指令是定長的32位元組。眾所周知,指令中操作碼是必須的字段,如果把32位立即數直接編碼到指令內部,操作碼就無「容身之地」了……
因此,arm指令中「立即數」的位數必小於32位。那麼如何在arm指令中正常表示立即數呢?我們看看arm的通用指令格式。
arm指令中,操作碼(opcode)、目的運算元(rd)、源運算元1(rn)是必須的字段。條件碼(cond)、符號位標記(s)源運算元2(oprand2)是可選的。其中rd和rn必須是暫存器,因此arm的「立即數」只能儲存在oprand2。
在arm的指令編碼內,使用「立即數」的指令為「立即數」提供了12bit的儲存空間,也就是說arm的「立即數」只能表示212=4096個數字。這顯然無法表示所有的32位立即數,如果使用這12bit表示0~4095的數字,那麼從4096~(232-1)的陣列都不能表示了。考慮到這種「後果」,arm指令集的設計者們使用了乙個技巧,即使用常數表示式代替立即數的概念。
常數表示式表示乙個常數,且該常數對應8位的點陣圖,即可以由乙個8位的常數通過迴圈移位偶數字得到。
比如0x3fc可以由8位常數0xff迴圈左移2位或迴圈右移30位得到,是常數表示式。再比如0x1fe,雖然可以有0xff迴圈左移1位或迴圈右移31位得到,但是移動的位數不是偶數,因此不是常數表示式。
根據常數表示式的定義,常數表示式只需要12bit的儲存空間。
空間中,低8位元組儲存8位位圖,高4位元組儲存迴圈右移的次數。4位元組只能表示24=16種移動次數,但是由於常數表示式定義中,移位限定為偶數次,因此這4個位元組剛好能表示0、2、4、6、8…32位16個數字!
比如0x3fc的二進位制表示為0xfff,即使用8位數字0xff迴圈右移0xf*2=30次得到。
明確了常數表示式的含義後,可以通過簡單的程式設計識別乙個數字是否是常數表示式。
/*
迴圈左移兩位
*/void roundleftshifttwobit(unsigned int& num)
/*判斷
num是否是常數表示式,
8位數字迴圈右移偶數字得到
*/bool constexpr(unsigned int num)
}roundleftshifttwobit
函式將乙個無符號32位整數迴圈左移2位,constexpr反覆將乙個無符號32位整數迴圈左移2位,直到發現該數字在0到0xff之間為止,否則表示該數字不是常數表示式。
通過常數表示式,arm指令便避免了「立即數」僅僅侷限於0~4095的數字範圍的問題了。但是常數表示式仍不能表示全部的32位整數,比如0x1fe。對於非常數表示式的數字,只能通過拆分來解決。
比如arm指令mov r0,#0x1fe不是合法的指令,因為0x1fe不是常數表示式。那麼只能將0x1fe拆分,表示為兩條指令,比如:
mov r0,#0xfe
add r0,r0,#0x100
除了拆分數字的方法,arm的ldr巨集使用臨時變數的方式實現非常數表示式的資料傳送,即:
ldr r0,=0x1fe
ldr巨集指令不是arm的真正指令,它由如下兩條指令實現:
.tmp .word 0x1fe
ldr r0,.tmp
ldr r0,[r0]
arm的ldr指令用於將記憶體的資料載入到暫存器。這裡數字0x1fe被儲存在ldr指令附近的位置.tmp處,ldr r0,.tmp被編譯為ldr r0,[pc+offset]的形式,其中offset為符號.tmp相對ldr指令的偏移。這樣ldr r0,.tmp獲取了符號.tmp的位址,然後再次使用ldr r0,[r0]將.tmp位址處的資料取出,即0x1fe。
通過以上的描述,我們明確了arm指令中常數表示式的真正含義,並基於此編寫了乙個驗證常數表示式的函式。最後,我們解析了如何在arm中實現非常數表示式資料的傳送,並討論了它的實現。希望對你理解arm的常數表示式有所幫助。 複製
去google翻譯
ARM的常數表示式
arm的常數表示式 如果說intel指令中的立即數,相信大家都很熟悉。類似的,arm指令中的 立即數 就是常數表示式。之所以稱為常數表示式,而不稱為立即數是有原因的。intel 指令屬於cisc指令集,指令是不定長的,因此可以將任意32位立即數編碼到指令內。arm指令屬於risc指令集,指令是定長的...
初探c 11之常數表示式
在c 11裡面,對於常數表示式有了更強的支援。乙個是函式返回值可以是常數,另外乙個是對於變數的常數表示式的支援更廣。首先,函式返回值可以是常數。這個值你可以把它用在所有可以用常數的地方,例如乙個陣列的大小。下面是乙個例子,來自wiki.constexpr int getfive int some v...
函式表示式
函式定義有以下兩種方式 一種是函式宣告,一種是函式表示式。函式宣告 在執行 之前會先讀取函式宣告,即函式宣告提公升。函式表示式 常用語法形式是常規的變數賦值語句,即建立乙個匿名函式並賦值給乙個變數。函式表示式在使用之前必須賦值,否則會出錯,這點與函式宣告提公升不同。能夠將匿名函式作為其他函式的值進行...