使用ldr命令注意事项
扫描二维码
随时随地手机看文章
今天犯了一个小错误,调试了几个小时;最后重新分析了几遍反汇编才发现。万丈高楼平地起、勿以浮沙驻高台。
错误代码:
.text .global _start _start: b reset ldr pc,=und_addr ldr pc,=swi_addr und_addr: .word undef swi_addr: .word swi_handle undef: ldr sp,=0x32000000 //处理异常调用C函数,设置und模式下的栈,以前是usr模式 //保存现场 stmdb sp!,{r0-r12,lr} bl print2 //处理异常 mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr低5位和usr模式的cpsr相同 ldr r1,=und_string bl printException //恢复现场 ldmia sp!,{r0-r12,pc}^ und_string: .string "undefined instruction exception" .align 4 swi_handle: ldr sp,=0x33000000 //处理异常调用C函数,设置svc模式下的栈,以前是usr模式 //保存现场 stmdb sp!,{r0-r12,lr} //处理异常 mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr低5位和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 // 比较r1和r2,即比较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_next sdram_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-littlearm Disassembly of section .text: 30000000: 30000000: ea00001e b 3000008030000004: e59ff110 ldr pc, [pc, #272] ; 3000011c 30000008: e59ff110 ldr pc, [pc, #272] ; 30000120 3000000c: 3000000c: 30000014 andcc r0, r0, r4, lsl r0 30000010: 30000010: 30000050 andcc r0, r0, r0, asr r0 ************************************************* 3000011c: 3000000c andcc r0, r0, ip 30000120: 30000010 andcc r0, r0, r0, lsl r0 ************************************************* 30000014: 30000014: e3a0d432 mov sp, #838860800 ; 0x32000000 30000018: e92d5fff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 3000001c: eb000103 bl 3000043030000020: e10f0000 mrs r0, CPSR 30000024: e59f10f8 ldr r1, [pc, #248] ; 30000124 30000028: eb000216 bl 300008883000002c: e8fd9fff ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^ 30000030: 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-littlearm Disassembly of section .text: *************************************** 3000011c: 30000014 andcc r0, r0, r4, lsl r0 30000120: 30000050 andcc r0, r0, r0, asr r0 *************************************** 30000000: 30000000: ea00001e b 3000008030000004: e59ff110 ldr pc, [pc, #272] ; 3000011c 30000008: e59ff110 ldr pc, [pc, #272] ; 30000120 3000000c: 3000000c: 30000014 andcc r0, r0, r4, lsl r0 30000010: 30000010: 30000050 andcc r0, r0, r0, asr r0 30000014: 30000014: e3a0d432 mov sp, #838860800 ; 0x32000000 30000018: e92d5fff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 3000001c: eb000103 bl 3000043030000020: e10f0000 mrs r0, CPSR 30000024: e59f10f8 ldr r1, [pc, #248] ; 30000124 30000028: eb000216 bl 300008883000002c: e8fd9fff ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^ 30000030: ... 30000050: 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-littlearm Disassembly of section .text: 30000000: 30000000: ea00001e b 3000008030000004: e59ff110 ldr pc, [pc, #272] ; 3000011c 30000008: e59ff110 ldr pc, [pc, #272] ; 30000120 ********************* 3000011c: 30000014 andcc r0, r0, r4, lsl r0 30000120: 30000050 andcc r0, r0, r0, asr r0 ********************* 3000000c: 3000000c: 30000014 andcc r0, r0, r4, lsl r0 30000010: 30000010: 30000050 andcc r0, r0, r0, asr r0 30000014: 30000014: e3a0d432 mov sp, #838860800 ; 0x32000000 30000018: e92d5fff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 3000001c: eb000103 bl 3000043030000020: e10f0000 mrs r0, CPSR 30000024: e59f10f8 ldr r1, [pc, #248] ; 30000124 30000028: eb000216 bl 300008883000002c: e8fd9fff ldmia sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^ 30000030: ... 30000050: 30000050: e3a0d433 mov sp, #855638016 ; 0x33000000 ...
结果:
总结:
注意ldr pc,=czg
与ldr pc,czg
用法:
① ldr pc,=czg
=》 pc = czg (就是czg标号的地址)
② ldr pc,czg
=》 pc = *(czg) (czg标号地址中放的值)