由于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