【问题标题】:ARM926ej-s reset handler - does it overwrite itself?ARM926ej-s 重置处理程序 - 它会覆盖自己吗?
【发布时间】:2013-12-12 08:31:01
【问题描述】:

我知道 ARM926ej-s 正在使用 全降序 堆栈。现在我有了这个启动代码,我在与此问题相关的行上使用/**/ 进行了评论。

.global __start
.global arm926ejs_reset
.global dcache_flush
.global __gnu_bssstart
.global __gnu_bssend
.global __image_size


.EQU MODE_USR,    0x010
.EQU MODE_FIQ,    0x011
.EQU MODE_IRQ,    0x012
.EQU MODE_SVC,    0x013
.EQU MODE_SVC_NI, 0x0D3
.EQU MODE_ABORT,  0x017
.EQU MODE_UNDEF,  0x01b
.EQU MODE_SYSTEM, 0x01f
.EQU MODE_BITS,   0x01f
.EQU I_MASK,      0x080
.EQU F_MASK,      0x040
.EQU IF_MASK,     0x0C0

.EQU BROM_MMU_BASE_ADDR, 0x1201C000 

.EQU MMU_DISABLE_MASK,   0xFFFFEFFA
.EQU MMU_ENABLE_MASK,    0x00001005

.EQU FIQ_STACK_SIZE,     128
.EQU IRQ_STACK_SIZE,     256
.EQU ABORT_STACK_SIZE,   32
.EQU UNDEF_STACK_SIZE,   32
.EQU SYSTEM_STACK_SIZE,  64

.text
.code 32
.align 2

__start:
arm926ejs_reset:
    B     arm926ejs_reset_handler     /*reset vector*/

.word   0x41676d69
.word   0,0,0,0,0
image_type:
.word   0x0000000A
sizeOfPermanentCode:    
    .word   (__image_size)
    .word   0,0
bootparameter:  
    .word   0
    .word   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

arm926ejs_reset_handler:

    MOV   r0, #MODE_SVC_NI
    MSR   cpsr_cxsf, r0

    MRC   p15, 0, r1, c1, c0, 0
    LDR   r2,=MMU_DISABLE_MASK
    AND   r1, r1, r2
    MCR   p15, 0, r1, c1, c0, 0

    MOV   r1,#0
    MCR   p15, 0, r1, c8, c7, 0

    MCR   p15, 0, r1, c7, c7, 0

    MRC   p15, 0, r1, c1, c0, 0
    LDR   r2,=0x1000
    ORR   r1, r1, r2
    MCR   p15, 0, r1, c1, c0, 0

    MVN   r1, #0
    MCR   p15, 0, r1, c3, c0, 0

    LDR   r3, =BROM_MMU_BASE_ADDR
    MCR   p15, 0, r3, c2, c0, 0

    LDR   r5, =inVirtMem

    MRC   p15, 0, r1, c1, c0, 0
    LDR   r2,=MMU_ENABLE_MASK
    ORR   r1, r1, r2
    MCR   p15, 0, r1, c1, c0, 0

    MOV   pc, r5

    NOP
    NOP
    NOP

inVirtMem:
    ADR   r3, arm926ejs_reset         /*we store the reset vector address*/
    SUB   r3, r3, #4                  /*why do we then substract 4 bytes?*/
    MOV   r1, #IF_MASK

    ORR   r0, r1, #MODE_FIQ           /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3                 
    SUB   r3, r3, #FIQ_STACK_SIZE


    ORR   r0, r1, #MODE_IRQ           /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #IRQ_STACK_SIZE

    ORR   r0, r1, #MODE_ABORT         /*sets stack for MCPU mode*/ 
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #ABORT_STACK_SIZE

    ORR   r0, r1, #MODE_UNDEF         /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #UNDEF_STACK_SIZE

    ORR   r0, r1, #MODE_SYSTEM        /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #SYSTEM_STACK_SIZE

    ORR   r0, r1, #MODE_SVC           /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3

    LDR   r0, =__gnu_bssstart
    LDR   r1, =__gnu_bssend
    MOV   r2, #0

clearzi:
    CMP   r0, r1
    BEQ   clearzi_exit
    STR   r2, [r0]
    ADD   r0, r0, #4
    B clearzi

clearzi_exit:

load_entry:
    LDR   pc, =c_entry
    NOP

dcache_flush:
    CMP   r0, #0
    BNE   inval

flushonly:
    MRC  p15, 0, r15, c7, c10, 3
    BNE  flushonly
    MOV  pc, lr

inval:
    MRC  p15, 0, r15, c7, c14, 3
    BNE  inval
    MOV  pc, lr

.END

在上面的代码中,第一条注释显示了一个重置​​向量(一个分支指令B arm926ejs_reset_handler),紧接着是一个标题和一些准备 mcu 的命令...

现在看下一条注释,我们将复位向量的地址存储到寄存器r3 中,在下一行中,我们从该地址中减去4 字节。

Q1:我们为什么要这样做?这个地址现在是否显示在.word 0x41676d69 的位置?

在下一行中有多个类似的块,每个块都为不同的 mcpu 模式设置堆栈。让我们看一下第一个堆栈指针sp 与寄存器r3 一起加载,然后从这个地址中减去堆栈的大小,得到这个mcpu 模式的堆栈大小。

Q2:此堆栈是否会覆盖从.word 0x41676d69 开始的标头以及用于准备MCU 的所有指令?重置向量B arm926ejs_reset_handler 保持不变吗?为什么我们要重写标题?我们不再需要它了吗?

【问题讨论】:

    标签: assembly stack arm


    【解决方案1】:

    现在看下一条注释,我们将复位向量的地址存储到寄存器 r3 中,在下一行中,我们从该地址中减去 4 个字节。

    Q1:我们为什么要这样做?这个地址现在是否显示在 .word 0x41676d69 的位置?

    通常代码递增。所以.word 0x41676d69 的值在 *arm926ejs_reset+4* 之后。当您减去时,您将 降序堆栈 的开始放在代码内存之前。

    Q2:此堆栈是否会覆盖从 .word 0x41676d69 开始的标头以及用于准备 mcu 的所有指令?重置向量 B arm926ejs_reset_handler 是否保持不变?为什么我们要重写标题?我们不再需要它了吗?

    不,它没有被覆盖。图像之前的内存用于堆栈。

    【讨论】:

    • 那么当减去 4 时,我们从 arm926ejs_reset 上移一行?然后当我们减去堆栈大小时,我们会进一步向上移动吗?我仍然不确定这一点。在 ARM 中,我们有一个完整的降序堆栈。我不太确定,但是当您提到“图像”时,您是指标题吗?我需要稍微澄清一下术语......
    • @71GA 图像是您放入包含指令的内存的二进制文件。您需要为不同的模式设置堆栈,因此您首先使用 FIQ、IRQ、ABORT、UNDEF、SYSTEM、SVC 指令之前的区域。而且它们确实被放置在指令区域之前,因为你用 SP 做减法。
    • 我也猜测 arm926ejs_reset 之前的命令将落入 .rodata 部分,我必须将此部分放在比 .text 部分更高的地址上,以免用堆栈覆盖这些常量?
    • .EQU MODE_USR, 0x10 是一个定义cpsr(当前程序状态寄存器)包含ARM mode。每种模式都有banked registers。您对 0x11028FFC 的地址计算是正确的。 .word 0x41676d69 将位于 0x11029004。如果您希望此代码正常工作,则不应在链接器文件中的.text 之前放置任何内容(如.rodata)。您可以使用 .stack (NOLOAD) : { . = . + 1k; _stack_top = .; }ld 在链接器文件中保留空间。
    • .equ 是一个定义(也称为指令)。 .align.data 是其他指令。比如#define 不同于#include#ifdef。如果你使用 GNU,那么Binutil docs 有答案; Directivesld options-M--print-map 制作地图文件。请看一下文件。阅读ldas 指令;它们一起有意义,尤其是对于部分
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多