测试代码

         ldr     r0, _start
        adr     r0, _start
        ldr     r0, =_start
        nop
        mov     pc, lr
_start:
        nop

   设置代码的起始地址为 0x0c008000,用 ADS1.2编译后的反汇编如下所示

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

0c008000 <_start-0x14>:
c008000:       e59f000c        ldr     r0, [pc, #12]   ; c008014 <_start>
c008004:       e28f0008        add     r0, pc, #8      ; 0x8
c008008:       e59f0008        ldr     r0, [pc, #8]    ; c008018 <_start+0x4>
c00800c:       e1a00000        nop                     (mov r0,r0)
c008010:       e1a0f00e        mov     pc, lr

0c008014 <_start>:
c008014:       e1a00000        nop                     (mov r0,r0)
c008018:       0c008014        stceq   0, cr8, [r0], -#80

分析: 

1、ldr     r0, _start

从内存地址 _start(0c008014) 的地方把值读入。执行这个后,r0 = 0xe1a00000。

2、adr     r0, _start

    通过指令“add     r0, pc, #8 ”把_start 的当前运行地址加载到 r0,它是与位置无关的。例如这段代码在 0x0c008000 运行,那么 adr r0, _start 得到 r0 = 0x0c008014;如果在地址 0 运行,就是 0x00000014 了。                                                                                                                                              

    那么通过这条伪指令就可以得知当前程序在内存的什么位置运行。这是一条伪指令,但是功能却如此强大,需要相应的编译器功能才能实现。

3、ldr     r0, =_start

这条指令取得的是标号_start 的绝对地址。这个绝对地址是在 link 的时候确定的。看上去这只是一个指令,但是它要占用 2 个 32bit 的空间,一条是指令,另一条是 _start 的数据(因为在编译的时候不能确定 _start 的值,而且也不能用 mov 指令来给 r0 赋一个 32bit 的常量,所以需要多出一个空间存放 _start 的真正数据,在这里就是 0x0c008014)。 

posted on 2013-11-12 15:59  amanlikethis  阅读(895)  评论(0编辑  收藏  举报