找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4134|回復: 0
打印 上一主題 下一主題
收起左側

從ARM匯編指令機器碼解釋一些問題

[復制鏈接]
跳轉到指定樓層
樓主
ID:107189 發(fā)表于 2016-3-6 15:26 | 只看該作者 |只看大圖 回帖獎勵 |正序瀏覽 |閱讀模式
本帖最后由 51黑tt 于 2016-3-6 15:28 編輯

從ARM匯編指令機器碼解釋一些問題

為什么MOV R0, #0×12345678這條指令無法編譯,而MOV R0, #0x678卻可以編譯通過?
為什么芯片會有立即數(shù)尋址,寄存器尋址,間接尋址等多種尋址方式?一種尋址方式不可以么?
為什么B跳轉指令只能跳轉到±32MBytes的范圍內?

下面,我們一起來看看ARM7的指令格式,從指令格式中找出這些問題的答案。

ARM7內核采用的是RISC精簡指令集,所有的ARM指令都是32bits的,在這32bits里既包含了指令的指令碼,也包含了指令需要運算的數(shù)據(jù),以MOV指令為例,通過MOV指令的32bits可以識別出這是一個MOV指令,又可以在這32bits里找到源寄存器和目的寄存器。我們來看一下MOV指令的機器碼格式:
圖 6  MOV指令的機器碼格式
28~31bitscond)是條件碼,就是表明這條語句里是否有大于、等于、非零等的條件判斷,這4bits共有16種狀態(tài),分別為:
二進制碼指令符號含義二進制碼指令符號含義
0000EQ相等0001NE不等
0010CS/HS進位/無符號數(shù)大于等于0011CC/LO清進位/無符號數(shù)小于
0100MI/負數(shù)0101PL/正數(shù)或0
0110VS溢出0111VC沒溢出
1000HI無符號數(shù)大于1001LS無符號數(shù)小于等于
1010GE有符號數(shù)大于等于1011LT有符號數(shù)小于
1100GT有符號數(shù)大于1101LE有符號數(shù)小于等于
1110AL任何條件1111-未定義
表 1  匯編語言條件碼
指令與條件碼可以有多種組合,比如MOV指令可以有MOV、MOVEQMOVLT等多種形式。前面我們說過狀態(tài)寄存器里有NZCV的狀態(tài)標志,當執(zhí)行一條指令時,芯片就會將這條指令的條件碼與狀態(tài)寄存器中的狀態(tài)標志做比較,如果狀態(tài)寄存器中的狀態(tài)標志滿足這條指令的條件碼時,則執(zhí)行這條語句,如果不滿足則不執(zhí)行這條指令。狀態(tài)寄存器中的狀態(tài)標志是受某些指令影響的,因此在使用有條件碼的指令進行判斷前,必然會有其它指令配合使用,先修改狀態(tài)寄存器中的狀態(tài)標志,例如:
CMP    R1, #0
BEQ    GETNEXTTASKSP
第一條指令“CMP”是一個“比較”指令,如果R1等于0,那么它就將狀態(tài)寄存器中的Z置為1,表示結果為真,否則,將狀態(tài)寄存器中的Z置為0,表示結果為假。第二條指令其實是一條“B”指令,是“跳轉”指令,B之后的“EQ”就是條件碼,從表1中可以知道,條件是“相等”時才執(zhí)行。
R1等于0時,CMP指令就將Z置為1,執(zhí)行BEQ時滿足條件,就執(zhí)行了跳轉。如果R1不等于0,CMP指令就將Z置為0,執(zhí)行BEQ時不滿足條件,就不執(zhí)行跳轉。
同理,只有當狀態(tài)寄存器中的標志為相等時,MOVEQ指令才會執(zhí)行,這時其功能與MOV指令相同。而MOVLT指令則是當狀態(tài)寄存器中的標志為有符號數(shù),并且處于小于狀態(tài)時才會執(zhí)行的MOV指令。MOV指令的條件碼是AL,因此MOV指令可以不管任何條件都去執(zhí)行。其它指令也可以與條件碼組合使用,具體情況請查閱參附錄中的參考文檔2。
25bitI)是用來區(qū)別shifer_operand域是采用立即數(shù)尋址方式還是寄存器尋址方式,該bit0表示寄存器尋址方式,為1表示立即數(shù)尋址方式,這就涉及到了指令的尋址方式。
尋址方式的出現(xiàn)不是為了使指令能有多種寫法,而是受指令長度限制被迫產生的產物。以MOV指令為例,如果采用立即數(shù)尋址,立即數(shù)的長度不可能超過shifer_operand域的長度(MOV指令可以采用移位的方式裝下部分更長的立即數(shù),這些不在討論之內),因此我們就不可能使用
MOV R0, #0×12345678
這條指令。立即數(shù)#0×1234567832bits數(shù)據(jù),已經超過了shifer_operand域所能裝下的最長12bits數(shù)據(jù),如果把0×12345678全部被存到指令中,那么該指令中將無法存儲條件碼等其它指令信息,因此,這條指令在編譯時就會報錯。
為了解決這個問題,芯片設計人員就設計了寄存器尋址方式,在ARM7中每種模式有16個通用寄存器,24次方等于16,因此只需要用4bits就可以為每個寄存器分配一個編號,R0~R15寄存器分別對應0~15的編號。4bits的寄存器編號完全可以存入shifer_operand域。采用寄存器尋址時,指令先查到寄存器的編號,然后再從寄存器中取出使用的數(shù)據(jù),這樣就解決了MOV指令受指令長度的限制而無法操作長立即數(shù)的問題。
從上述描述的過程來看采用寄存器尋址方式必須先將數(shù)據(jù)放入一個寄存器中,然后才能使用MOV指令采用寄存器尋址。對比立即數(shù)尋址方式,它增加了指令的執(zhí)行時間,也增加了代碼,還多用了一個寄存器,但它的優(yōu)點是可以操作長的數(shù)據(jù)。
除了上面這兩種尋址方式外,ARM7還有多種其它尋址方式,每種尋址方式都有其自身的特點,適用不同的場景,這里不介紹了。
21~24bitsopcode)是指令碼,用來表明這條指令是什么指令,例如,MOV指令的指令碼是0b1101,看到0b1101,芯片就將這條指令當做MOV指令來解析。
20bitS)就是指令中S標志的體現(xiàn),該bits0表示指令不帶S,為1表示指令帶S,功能見上述指令介紹。
16~19bitsSBZ)手冊中沒查到是什么意思,SBZ應該是should be zero的意思,對比了幾條指令發(fā)現(xiàn)該域果然全是0,應該是保留位。
12~15bitsRd)是指令中的目的寄存器,存放寄存器的4bits編號。
0~11bitsshifter_operand),指令的操作數(shù)。

下面我找了4條指令,將MOV指令做一個對比:
指令
機器碼
指令格式
cond00IopcodeSSBZRdshifer_operand
MOV R1, #0×64E3A0106411100011101000000001000001100100
條件碼為1110適用任何條件 立即數(shù)方式MOV的指令碼指令沒有S標志 目的寄存器為R1源操作數(shù)為立即數(shù)0×64
MOVS PC, R14E1B0F00E11100001101100001111000000001110
條件碼為1110適用任何條件 寄存器方式MOV的指令碼指令有S標志 目的寄存器為R15源操作數(shù)為寄存器R14
MOVLT R3, #0×1B3A0300110110011101000000011000000000001
LT的條件碼為1011 立即數(shù)方式MOV的指令碼指令沒有S標志 目的寄存器為R3源操作數(shù)為立即數(shù)1
MOVEQ R0, R101A0000100000001101000000000000000000001
EQ的條件碼為0000 寄存器方式MOV的指令碼指令沒有S標志 目的寄存器為R0源操作數(shù)為寄存器R1
表 2  MOV指令匯編格式對比

BL指令跳轉到目的地址,同時將BL指令的下條指令地址存入LR寄存器供程序返回時使用,調用函數(shù)時可以使用BL指令,如:
0×00080398 EB0002E2  BL    0x00080F28
0×00080398BL指令所在的地址,EB0002E2BL指令的機器碼,0x00080F28BL指令要跳轉到的地址。從這個格式來看,BL指令好像是一個絕對跳轉指令,直接跳轉到0x00080F28這個地址,其實不然,BL指令是一個相對跳轉指令,格式如下:



BL指令的0~23bits存放的是要跳轉的相對地址,由于指令所在地址必須是4字節(jié)對齊的,因此跳轉的地址最低2bits必然是0,因此BL指令0~23bits保存的是省略這最低2bits的地址,如果補全了這2bitsBL指令就可以表示26bits的跳轉地址。在這26bits中需要使用1bit表示向前跳還是向后跳,那么剩下的25bits就可以表示32MByts的范圍了,225=32M,因此,我們在很多文檔上可以看到B跳轉指令只能跳轉到±32MBytes范圍內的說明,就是這個原因。
上面這個BL指令要跳轉的相對地址是0x2E2BL指令0~23bits),補充2個最低位后,跳轉的相對地址為0xB88,由于ARM72級流水線,所以跳轉到的指令需要多加8個字節(jié),BL要跳轉的實際地址為0×00080398+0xB88+8=0x00080F28。
這條BL指令執(zhí)行下面的操作:
LR = 0x0008039C
PC = 0x00080F28
在操作系統(tǒng)中我們沒有使用BL指令,就是因為我們不知道我們所調用的函數(shù)是否會超出BL指令的跳轉范圍,但我們可以看到編譯器編譯出的很多程序都是使用BL指令調用函數(shù)的,編譯器之所以不怕跳轉超出±32MBytes的范圍,是因為編譯器在編譯時就知道了程序所需要跳轉的范圍,它會為±32MBytes之內的跳轉分配BL指令,保證BL指令不會超出范圍。在這里以BL指令為例,介紹一下B指令的相關知識。



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表