2014-02-23 73 views
1

我讀到Cortex-M3中只有拇指指針,無論何時寫入PC,我們都必須確保目標地址LSB爲1以確保處理器保持在拇指模式下。另外,當我們使用'BX reg'時,reg值必須有LSB = 1來啓用拇指模式。在Cortex-M3中使用B指令(thumb)

我們在cortex-m3中使用'B標籤'的情況如何?由於16位/ 32位指令與偶數地址對齊,因此此「標籤」將具有LSB = 0的值。 'B標籤'不等於'PC:=標籤'嗎?

'B標籤'和'BL標籤'特殊情況下,PC的寫入不會影響處理器模式?

謝謝。

回答

1

目標地址需要bx(和blx)指令的lsbit a 1,當它進入pc時,1被剝離。 b指令是pc相對的,arm文檔中顯示的數學表明它是平坦的。

一般而言,如果您讓這些工具完成工作,您無需隨時爲此擔心。

thumb.s

.thumb 

.globl _start 
_start: 
    b reset 
    nop 
    nop 
.thumb_func 
reset: 
    nop 
    nop 
    nop 
    nop 
    ldr r0,=reset 
    bx r0 

然後

arm-none-eabi-as thumb.s -o thumb.o 
arm-none-eabi-ld -Ttext=0x1000 thumb.o -o thumb.elf 
arm-none-eabi-objdump -D thumb.elf 

這給

thumb.elf:  file format elf32-littlearm 


Disassembly of section .text: 

00001000 <_start>: 
    1000: e001  b.n 1006 <reset> 
    1002: 46c0  nop   ; (mov r8, r8) 
    1004: 46c0  nop   ; (mov r8, r8) 

00001006 <reset>: 
    1006: 46c0  nop   ; (mov r8, r8) 
    1008: 46c0  nop   ; (mov r8, r8) 
    100a: 46c0  nop   ; (mov r8, r8) 
    100c: 46c0  nop   ; (mov r8, r8) 
    100e: 4801  ldr r0, [pc, #4] ; (1014 <reset+0xe>) 
    1010: 4700  bx r0 
    1012: 10070000 andne r0, r7, r0 
    ... 

分支需要照顧本身

1000: e001  b.n 1006 <reset> 
...  
00001006 <reset>: 

分支中的編碼以16位量爲單位,而不是以字節爲單位,然後它們乘以2(移位它)以獲得總是偶數的字節地址。電腦從來不會奇怪,這是你喂bx或blx奇怪的值。

現在,因爲我在復位之前使用了.thumb_func,它告訴彙編器,這是一個拇指標籤,而不是臂標籤。所以當我說的時候,請將reset的地址加載到r0中,然後彙編器爲0x00001007分配一些數據,這在反彙編中顯得很奇怪,但它在那裏。他們已經爲我們樹立

00001006 <reset>: 
... 
    100e: 4801  ldr r0, [pc, #4] ; (1014 <reset+0xe>) 
    1010: 4700  bx r0 
    1012: 10070000 andne r0, r7, r0 

,所以LSb現在,如果你要刪除.thumb_func

100c: 46c0  nop   ; (mov r8, r8) 
100e: 4801  ldr r0, [pc, #4] ; (1014 <reset+0xe>) 
1010: 4700  bx r0 
1012: 10060000 andne r0, r6, r0 

彙編認爲它是手臂地址,不設置和,所以LSb該代碼會崩潰。現在,如果你關心它,你總是可以添加額外的orr r0,#1,但這真的只是一個黑客。瞭解您正在使用的彙編程序如何將標籤聲明爲拇指標籤而不是手臂。是的,gnu彙編程序知道這段代碼段是拇指,這似乎很愚蠢,因爲我們告訴它,但它無法弄清楚拇指代碼中的標籤是...拇指標籤。非常愚蠢的工具。

而且我會假設還有其他更詳細的gnu彙編程序指令,這些指令也允許您聲明這個函數或拇指標籤或其他。當然,每個彙編程序都是不同的,所以不要假定gnu彙編程序指令適用於其他彙編程序指令。

如果你混合使用C和asm,C編譯器不是愚蠢的,它知道-mthumb使得所有的函數和全局變量(標籤)變成了拇指,並且取決於你在代碼中使用它們的方式和位置,鏈接器放置了正確的值。它甚至可以爲您正確切換模式,其中主要是手臂代碼的拇指代碼,並在切換模式的代碼中放置一個蹦牀。反之亦然,至少我已經看到這個工具可以做到這一點(並且在堆棧溢出答案中多次展示了它)。我不記得讓它工作與否是非常棘手的,你應該定期反編譯,並確保鏈接器爲你做這件事,否則就這樣做,或者你總是可以自己動手做。

所以

請記住,只有BX和BLX需要一套,所以LSb拇指和兩個個LSb重置分支武裝。 blx和bx指令將刪除該lsbit,並在pc中保留一個偶數編號的pc(非常簡單,請執行mov r0,pc然後用拇指代碼查看它)。

理想情況下,無條件和有條件的分支(而不是bx)不應該將模式分爲手臂和拇指。同樣的BL,但我已經看到GNU工具幫助了這一點,如果你想要你的代碼純然後加載地址在工具必須做的權利,否則整個工具鏈是一個失敗的寄存器,blx而不是BL該標籤並不依賴於爲你做蹦牀的工具鏈。

1

是不是'B標籤'等同於'PC:=標籤'?

它實際上是PC := PC + offset * 2,其偏移量在指令中編碼。彙編器/鏈接器必須計算此偏移量。

有關指令編碼的詳細信息,請參閱ARMv7-M的ARM體系結構參考手冊。

是'B標籤'和'BL標籤'例外的情況下,電腦的寫作不會影響處理器模式?

是。最後一位是而不是編碼在B(L) label指令中,所以無法更改縮略模式位。