ARM926ej-s重置处理程序 - 它会覆盖自身吗?

时间:2013-11-26 23:08:28

标签: assembly stack arm

我知道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

的位置

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

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

1 个答案:

答案 0 :(得分:2)

  

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

     

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

通常代码增量。所以值.word 0x41676d69在* arm926ejs_reset + 4 *之后。减去时,将降序堆栈的开头放在代码存储器之前。

  

Q2:此堆栈是否会覆盖.word 0x41676d69上的标头以及用于准备mcu的所有指令?复位向量B arm926ejs_reset_handler是否保持不变?为什么我们owerwrite标头?我们不再需要了吗?

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