我有ARM926ej-s的启动代码,它支持ISA ARMv5TEJ。启动代码如下所示,但为了清楚起见,我用注释切换了一些命令/数据。对我来说仍然不清楚的行标有“@???????????????????????????????????????????????????????
”注释。
我想知道,为什么我们需要从寄存器“#4
”中存储的值(arm926ejs_reset
“的位置)中减去”r3
“?然后在4行之后将其加载到堆栈指针中,我们为第一个处理器模式设置堆栈,这是快速中断模式。
__start:
arm926ejs_reset:
@here there is image header data needed by ISROM
arm926ejs_reset_handler:
@here we disable MMU, I-cache, D-cache, flush them... and prepare the mcpu.
LDR r5, =inVirtMem
@here we enable MMU.
MOV pc, r5
NOP
NOP
NOP
inVirtMem:
ADR r3, arm926ejs_reset @load location of "arm926ejs_reset" label in r3
MOV r1, #IF_MASK
SUB r3, r3, #4 @???????????????????????????????????????????????????????
ORR r0, r1, #MODE_FIQ
MSR cpsr_cxsf, r0
MOV sp, r3 @???????????????????????????????????????????????????????????
SUB r3, r3, #FIQ_STACK_SIZE
...
答案 0 :(得分:1)
我在网上找到了类似的启动代码,这些代码的代码评论很好。在此start up code中,您可以在Line 186
上看到r3
指向MMU
基地址。 MMU
跨越其基地址。即如果MMU_BASE_ADDRESS
= 0x400,则MMU
条目将位于0x400
,0x404
0x408
等。现在Line 217
r3
被减去4然后被分配到SP
上的Line 222
。如果我们不减去4,我们的第一个堆栈条目(观察堆栈在MMU
布局的反方向上增长)将覆盖第一个MMU
条目!因此减法。
同样在您的示例中,如果我们不减去4,您的堆栈将覆盖重置处理程序本身。你的程序会去折腾。
另一个例子是start up code,它们将结束IRAM
并减去4. IRAM的结尾意味着在IRAM
之外,因此减法进入IRAM
{1}}
观察到这个特定的例子(或者更低的地址)堆栈正在增长。(ARM堆栈可以以任何方式增长)
答案 1 :(得分:0)
我的猜测:堆栈位于下面标签(可能是写入标签会是一件坏事),所以作者虽然需要被调低一个字。
这看起来很奇怪 - 通常堆栈在完全降序模式下使用,因此堆栈指针的初始值永远不会被写入。除非你能证明这一点,否则我不会感到惊讶,如果这是一个(无害的)错误。
可能可能在您显示的代码段之外保留一个堆栈空间用于自己的用途吗?