为什么我们从arm926ej reset中减去4才能将它加载到sp?

时间:2012-03-06 12:35:08

标签: assembly arm startup

我有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

...

2 个答案:

答案 0 :(得分:1)

我在网上找到了类似的启动代码,这些代码的代码评论很好。在此start up code中,您可以在Line 186上看到r3指向MMU基地址。 MMU跨越其基地址。即如果MMU_BASE_ADDRESS = 0x400,则MMU条目将位于0x4000x404 0x408等。现在Line 217 r3被减去4然后被分配到SP上的Line 222。如果我们不减去4,我们的第一个堆栈条目(观察堆栈在MMU布局的反方向上增长)将覆盖第一个MMU条目!因此减法。

同样在您的示例中,如果我们不减去4,您的堆栈将覆盖重置处理程序本身。你的程序会去折腾。

另一个例子是start up code,它们将结束IRAM并减去4. IRAM的结尾意味着在IRAM之外,因此减法进入IRAM {1}}

观察到这个特定的例子(或者更低的地址)堆栈正在增长。(ARM堆栈可以以任何方式增长)

答案 1 :(得分:0)

我的猜测:堆栈位于下面标签(可能是写入标签会是一件坏事),所以作者虽然需要被调低一个字。

这看起来很奇怪 - 通常堆栈在完全降序模式下使用,因此堆栈指针的初始值永远不会被写入。除非你能证明这一点,否则我不会感到惊讶,如果这是一个(无害的)错误。

可能可能在您显示的代码段之外保留一个堆栈空间用于自己的用途吗?