由於ARM加載立即數據的能力有限,因此爲ARM生成代碼的實用程序經常並置代碼和數據。例如,像
void myRoutine(void)
{
myVar1=0x12345678;
myVar2=0x87654321;
}
聲明可能最終成爲類似:
myRoutine:
ldr r0,=myVar1; Load the address of _myVar
ldr r1,=0x12345678
str r1,[r0]
ldr r0,=myVar1; Load the address of _myVar
ldr r1,=0x87654321
str r1,[r0]
bx lr
which would get translated into:
ldr r0,dat1
ldr r1,dat2
str r1,[r0]
ldr r0,dat3
ldr r1,dat4
str r1,[r0]
bx lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678
or perhaps even something like:
mar r0,dat1
ldrm r0,[r1,r2,r3,r4]
str r2,[r1]
str r4,[r3]
bx lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678
注意_myVar和0x12345678的可以立即放置在它們出現的程序代碼如下;如果您嘗試使用最後一條指令後面的標籤來確定例程的長度,則此長度將無法包含補充數據。
與ARM需要注意的另外一點是,由於歷史的原因,代碼的地址會經常有,雖然代碼實際上開始於半字的邊界他們最顯著位爲偶數。因此,地址爲0x12345679的指令將佔用從0x12345678開始的兩個或四個字節。這可能會使memcpy之類的地址計算複雜化。
我的建議是用匯編語言編寫一個小的程序,做你所需要的。這只是一些說明,您可以確切知道代碼正在做什麼以及它可能具有哪些地址依賴關係,並且您不必擔心未來的編譯器版本會以某種方式更改您的代碼,從而導致破壞某些內容[例如,上面的代碼的第三個版本也沒問題,即使dat1
降落奇數半字邊界由於M3的LDR指令可以處理未對齊的讀取,但第四(略更快和更緊湊),使用LDRM在這樣的情況下會失敗版本;即使當今版本的編譯器使用四條LDR指令,未來的版本也可能使用LDRM]。
嗯,我認爲你應該多或交小於製造商的論壇,您使用的是特殊的硬件,但是,你能不能提供更多的細節,你使用的是什麼編譯器,你怎麼調試它,任何代碼樣本,也許*一個*有知識的人可以回答這個問題,除此之外...... – t0mm13b 2010-06-15 09:39:20
@ tommieb75:但我更喜歡你們! – c0m4 2010-06-15 09:42:36