Chinaunix首页 | 论坛 | 博客
  • 博客访问: 307927
  • 博文数量: 20
  • 博客积分: 3011
  • 博客等级: 中校
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-12 10:01
文章分类

全部博文(20)

文章存档

2008年(20)

我的朋友

分类: LINUX

2008-03-05 18:23:35

    
     arm平台下使用bl和ldr跳转应当注意的地方(arm-linux-gcc环境)
         作者 :  MSN:

一,按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 <.data>:
   0: e3a0da01  mov sp, #4096 ; 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: 2029554e  eorcs r5, r9, 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, #4096 ; 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: 2029554e  eorcs r5, r9, 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 <.data>:
       0: e3a0da01  mov sp, #4096 ; 0x1000
       4: e59ff000  ldr pc, [pc, #0] ; 0xc
       8: eafffffe  b 0x8
       c: 30000000  andcc r0, r0, r0
 ...
    1000: e4d10001  ldrb r0, [r1], #1
    1004: e4c20001  strb r0, [r2], #1
    1008: e3a00000  mov r0, #0 ; 0x0
    100c: e1a0f00e  mov pc, lr
    1010: 43434700  cmpmi r3, #0 ; 0x0
    1014: 4728203a  undefined
    1018: 2029554e  eorcs r5, r9, lr, asr #10
    101c: 2e332e33  mrccs 14, 1, r2, cr3, cr3, {1}
    1020: 00000032  andeq r0, r0, r2, lsr r0
可以看到4: e59ff000  ldr pc, [pc, #0] ; 0xc
这条命令将跳转到0x30000000处开始执行
阅读(2691) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-03-22 17:29:30

是gcc环境,用的编译器是arm-elf-gcc等编译工具,就是总是报错,连接脚本里的就没错,可就是到汇编语言中就不对了,这种格式好像不属于arm汇编,应该怎样解决,是不是缺少什么编译选项。。。。

panhuachun2008-03-20 18:08:05

我这个是gcc环境,你用的是什么环境的啊?ads和着个有差别

chinaunix网友2008-03-19 20:26:57

你好, 我遇到一个问题,就是在汇编文件中不能识别用.global定义的全局变量,编译的时候编译器总是报错global前面的点,这些特殊的符号好像不属于arm的汇编怎样解决,麻烦指点一下。