使用ldr命令注意事项

来源:互联网 发布:淘宝直播申请不过 编辑:程序博客网 时间:2024/06/06 01:25

今天犯了一个小错误,调试了几个小时;最后重新分析了几遍反汇编才发现。万丈高楼平地起、勿以浮沙驻高台。


错误代码:

.text.global _start_start:    b reset    ldr pc,=und_addr    ldr pc,=swi_addrund_addr:    .word undefswi_addr:    .word swi_handleundef:    ldr sp,=0x32000000 //处理异常调用C函数,设置und模式下的栈,以前是usr模式    //保存现场    stmdb sp!,{r0-r12,lr}    bl print2    //处理异常    mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr5位和usr模式的cpsr相同    ldr r1,=und_string    bl printException    //恢复现场    ldmia sp!,{r0-r12,pc}^und_string:    .string "undefined instruction exception".align 4swi_handle:     ldr sp,=0x33000000 //处理异常调用C函数,设置svc模式下的栈,以前是usr模式    //保存现场    stmdb sp!,{r0-r12,lr}    //处理异常    mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr5位和svc模式的cpsr相同    ldr r1,=swi_string    bl printException    //恢复现场    ldmia sp!,{r0-r12,pc}^swi_string:    .string "swi exception".align 4    reset://关看门狗    ldr r1,=0x53000000    ldr r0,=0    str r0,[r1]//设置时钟    //① 设置锁定时间LOCKTIME    ldr r1,=0x4C000000    ldr r0,=0xFFFFFFFF    str r0,[r1]    //② 设置分频系数,使得FCLK:HCLK:PCLK = 8:4:1    ldr r1,=0x4C000014    ldr r0,=0x5    str r0,[r1]    //③ 根据2440规则,由于②中HDIVN!=0 -> CPU总线模式从快速总线模式到异步模式    mrc p15,0,r0,c1,c0,0    orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA    mcr p15,0,r0,c1,c0,0    //④ 设置PLL,设置完PLL后,PLL开始工作,锁定时间内CPU停止工作    /* 设置FCLK = 400MHZ,HCLK = 100MHZ, PCLK = 100MHZ      * Mpll(FCLK) = (2*m * Fin) / (p * 2^s)     * m = M(MDIV) (the value for divider M)+ 8,     * p = P(PDIV) (the value for divider P) + 2, s = SDIV     * MDIV = 92(0x5c), PDIV = 1 , SDIV = 1      * FCLK = (2*100*12MHZ) / (3*2^1) = 400MHZ */     ldr r1,=0x4C000004     ldr r0,= ((92<<12) | (1<<4) | (1<<0))     str r0,[r1]//判断启动方式    mov r1,#0 // r1 = 0;    ldr r0,[r1] // r0 = [0];将0地址的值备份    str r1,[r1] // 将0写入0地址    ldr r2,[r1] // 再将0地址的值读出来给r2    cmp r1,r2   // 比较r1r2,即比较0地址原来的值和写入的值    ldr sp,= 0x40000000 + 4096 // 先假设为nor启动    ldreq sp,= 4096 //如果r1==r2,假设不成立为Nand启动    streq r0,[r1]   // 还原0地址以前的值    bl sdram_init    //bl sdram_init2 //用到有初始值的数组,不是位置无关码        bl copy2sdram       bl clean_bss    //从复位后的SVC模式切换到USR模式    //M[4:0] SVC:10011 USR:10000     mrs r0,cpsr    bic r0,r0,#0xf //修改低四位,进入usr模式    msr cpsr,r0    //设置usr模式下的栈,sp_usr    ldr sp,=0x34000000;    ldr pc,=sdram_nextsdram_next:         bl uart0_init    mrs r0,cpsr  //SVC模式下的cpsr寄存器    bl print1    bl print2    swi 0x1  /* 执行此命令, 触发SWI异常, 进入0x8执行 */und_code:    .word 0xeeadc0de  /* 未定义指令 */    bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */    //ldr pc, =main  /* 绝对跳转, 跳到SDRAM */halt:    b halt

结果:

这里写图片描述

分析:

sdram.elf:     file format elf32-littlearmDisassembly of section .text:30000000 <_start>:30000000:   ea00001e    b   30000080 <reset>30000004:   e59ff110    ldr pc, [pc, #272]  ; 3000011c <.text+0x11c>30000008:   e59ff110    ldr pc, [pc, #272]  ; 30000120 <.text+0x120>3000000c <und_addr>:3000000c:   30000014    andcc   r0, r0, r4, lsl r030000010 <swi_addr>:30000010:   30000050    andcc   r0, r0, r0, asr r0*************************************************3000011c:   3000000c    andcc   r0, r0, ip30000120:   30000010    andcc   r0, r0, r0, lsl r0*************************************************30000014 <undef>:30000014:   e3a0d432    mov sp, #838860800  ; 0x3200000030000018:   e92d5fff    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}3000001c:   eb000103    bl  30000430 <print2>30000020:   e10f0000    mrs r0, CPSR30000024:   e59f10f8    ldr r1, [pc, #248]  ; 30000124 <.text+0x124>30000028:   eb000216    bl  30000888 <printException>3000002c:   e8fd9fff    ldmia   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^30000030 <und_string>:30000030:   65646e75    strvsb  r6, [r4, #-3701]!........

发生异常的时候,异常向量表中pc没有跳转到相应的执行函数地址,因为我采用了间接的赋值。两次异常都是跳转到und_addr或者swi_addr开始往后面执行,所以两次都执行了undef处理函数。

更正测试:

①直接赋值到对应执行函数处

.text.global _start_start:    b reset    ldr pc,=undef    ldr pc,=swi_handle

反汇编:

sdram.elf:     file format elf32-littlearmDisassembly of section .text:***************************************3000011c:   30000014    andcc   r0, r0, r4, lsl r030000120:   30000050    andcc   r0, r0, r0, asr r0***************************************30000000 <_start>:30000000:   ea00001e    b   30000080 <reset>30000004:   e59ff110    ldr pc, [pc, #272]  ; 3000011c <.text+0x11c>30000008:   e59ff110    ldr pc, [pc, #272]  ; 30000120 <.text+0x120>3000000c <und_addr>:3000000c:   30000014    andcc   r0, r0, r4, lsl r030000010 <swi_addr>:30000010:   30000050    andcc   r0, r0, r0, asr r030000014 <undef>:30000014:   e3a0d432    mov sp, #838860800  ; 0x3200000030000018:   e92d5fff    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}3000001c:   eb000103    bl  30000430 <print2>30000020:   e10f0000    mrs r0, CPSR30000024:   e59f10f8    ldr r1, [pc, #248]  ; 30000124 <.text+0x124>30000028:   eb000216    bl  30000888 <printException>3000002c:   e8fd9fff    ldmia   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^30000030 <und_string>:...30000050 <swi_handle>:30000050:   e3a0d433    mov sp, #855638016  ; 0x33000000...

结果:
这里写图片描述


② 间接赋值

.text.global _start_start:    b reset    ldr pc,und_addr    ldr pc,swi_addr

反汇编:

sdram.elf:     file format elf32-littlearmDisassembly of section .text:30000000 <_start>:30000000:   ea00001e    b   30000080 <reset>30000004:   e59ff110    ldr pc, [pc, #272]  ; 3000011c <.text+0x11c>30000008:   e59ff110    ldr pc, [pc, #272]  ; 30000120 <.text+0x120>*********************3000011c:   30000014    andcc   r0, r0, r4, lsl r030000120:   30000050    andcc   r0, r0, r0, asr r0*********************3000000c <und_addr>:3000000c:   30000014    andcc   r0, r0, r4, lsl r030000010 <swi_addr>:30000010:   30000050    andcc   r0, r0, r0, asr r030000014 <undef>:30000014:   e3a0d432    mov sp, #838860800  ; 0x3200000030000018:   e92d5fff    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}3000001c:   eb000103    bl  30000430 <print2>30000020:   e10f0000    mrs r0, CPSR30000024:   e59f10f8    ldr r1, [pc, #248]  ; 30000124 <.text+0x124>30000028:   eb000216    bl  30000888 <printException>3000002c:   e8fd9fff    ldmia   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^30000030 <und_string>:...30000050 <swi_handle>:30000050:   e3a0d433    mov sp, #855638016  ; 0x33000000...

结果:
这里写图片描述


总结:

注意ldr pc,=czgldr pc,czg 用法:
ldr pc,=czg =》 pc = czg (就是czg标号的地址)
ldr pc,czg =》 pc = *(czg) (czg标号地址中放的值)