arm平台下使用bl和ldr跳转应当注意的地方(arm-linux-gcc环境)发布时间:2008-01-02 02:23:00 来源: ChinaUnix博客 作者: ChinaUnix博客 点击:949 arm平台下使用bl和ldr跳转应当注意的地方(arm-linux-gcc环境) 作者 : MSN: panhuachun@hotmail.com 一,按lds文件连接的不同模块,不能用bl实现跳转 一个错误的例子: 1.crt0.s @****************************************************************************** @ File:crt0.s @ 功能:通过它转入C程序 @****************************************************************************** .extern main .text .global _start _start: ldr sp, =1024*4 @设置堆栈,注意:不能大于4k , @这儿堆栈可以设置为0x34000000,根据内存地址空间分配确定 bl main @调用C程序中的main函数 halt_loop: b halt_loop 2.leds.c @****************************************************************************** @ file leds.c @ main函数 @****************************************************************************** int main() { __asm__ ( " ldrb r0, [r1], #1\n" " strb r0, [r2], #1\n" ); return 0; } 3.Makefile CFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding -c leds : crt0.s leds.c arm-linux-gcc $(CFLAGS) -o crt0.o crt0.s arm-linux-gcc $(CFLAGS) -o leds.o leds.c arm-linux-ld -Tleds.lds crt0.o leds.o -o leds_tmp.o arm-linux-objcopy -O binary -S leds_tmp.o leds arm-linux-objdump -D -b binary -m arm leds >ttt.s clean: rm -f leds rm -f leds.o rm -f leds_tmp.o rm -f crt0.o 4.leds.lds 文件 SECTIONS { firtst 0x00000000 : { crt0.o } second 0x00000000 : AT(0x0100) { leds.o } } 5.反汇编代码ttt.s 00000000 : 0: e3a0da01 mov sp, #40Array6 ; 0x1000 4: ebfffffd bl 0x0 //这儿不能调转到main 因为bl跳转有限制 8: eafffffe b 0x8 ... 100: e24dd040 sub sp, sp, #64 ; 0x40 104: e3a00000 mov r0, #0 ; 0x0 108: e28dd040 add sp, sp, #64 ; 0x40 10c: e1a0f00e mov pc, lr 110: 43434700 cmpmi r3, #0 ; 0x0 114: 4728203a undefined 118: 202Array554e eorcs r5, rArray, lr, asr #10 11c: 2e332e33 mrccs 14, 1, r2, cr3, cr3, {1} 120: 00000032 andeq r0, r0, r2, lsr r0 通过上面的例子可以看到crt0中的bl main出错 "4: ebfffffd bl 0x0 " bl没有成功。 6.改正方法1: 原lds文件把俩个目标文件分开排列,这里把俩个目标文件指定到一起,这样不能重定位。 修改后的lds文件 SECTIONS { firtst 0x00000000 : { crt0.o leds.o } } 改正后的效果 0: e3a0da01 mov sp, #40Array6 ; 0x1000 4: eb000000 bl 0xc //这里bl跳转到正确的地址 8: eafffffe b 0x8 c: e24dd040 sub sp, sp, #64 ; 0x40 10: e3a00000 mov r0, #0 ; 0x0 14: e28dd040 add sp, sp, #64 ; 0x40 18: e1a0f00e mov pc, lr 1c: 43434700 cmpmi r3, #0 ; 0x0 20: 4728203a undefined 24: 202Array554e eorcs r5, rArray, lr, asr #10 28: 2e332e33 mrccs 14, 1, r2, cr3, cr3, {1} 2c: 00000032 andeq r0, r0, r2, lsr r0 二,使用ldr命令来实现长跳转(改正方法2) 1. ldr pc, =main @调用C程序中的main函数 通过ldr 对pc赋值来实现跳转 @****************************************************************************** @ File:crt0.s @ 功能:通过它转入C程序 @****************************************************************************** .extern main .text .global _start _start: ldr sp, =1024*4 @设置堆栈,注意:不能大于4k,nand flash中的代码在复位后会移到内部ram中,此ram只有4k ldr pc, =main @调用C程序中的main函数 halt_loop: b halt_loop 2.leds.lds文件 SECTIONS { firtst 0x00000000 : { crt0.o } second 0x30000000 : AT(0x1000) { leds.o } } 3.反汇编结果 00000000 : 0: e3a0da01 mov sp, #40Array6 ; 0x1000 4: e5Arrayff000 ldr pc, [pc, #0] ; 0xc 8: eafffffe b 0x8 c: 30000000 andcc r0, r0, r0 ... 1000: e4d10001 ldrb r0, [r1], #1 本文来自ChinaUnix博客,如果查看原文请点:http://blog./u1/33226/showart_4Array0067.html |
|