adr与ldr的区别2

来源:互联网 发布:贾敏 知乎 编辑:程序博客网 时间:2024/05/17 21:06

在学习ARM指令时,经常会对adr和ldr这两个命令产生疑惑,那他们究竟有什么区别呢?其实这两个都是伪指令:adr是小范围的地址读取伪指令,相于PC 寄存器或其它寄存器的小范围转移;ldr是大范围的读取地址伪指令,相当于PC 寄存器或其它寄存器的长转移。

看下面的例子:

        AREA test, CODE, READONLY
                ENTRY

start
                ldr r0, _start
                nop
                nop
                adr r0, _start
                nop
                nop
                ldr r0, =_start
                nop
                nop

_start
                nop

                END

反汇编后的结果:

        1    0x00000000:    e59f001c       ....    LDR    r0,[pc,#28] ; [0x24] = 0xe1a00000
        2    0x00000004:    e1a00000     ....    MOV r0,r0
        3    0x00000008:    e1a00000     ....     MOV r0,r0
        4    0x0000000c:    e28f0010       ....    ADD r0,{pc}+0x18 ; 0x24
        5    0x00000010:    e1a00000     ....    MOV r0,r0
        6    0x00000014:    e1a00000     ....    MOV r0,r0
        7    0x00000018:    e59f0008       ....    LDR r0,[pc,#8] ; [0x28] = 0x24
        8    0x0000001c:    e1a00000      ....    MOV    r0,r0
        9    0x00000020:    e1a00000      ....    MOV    r0,r0
        _start
        10    0x00000024:    e1a00000    ....    MOV    r0,r0
        $d
        11    0x00000028:    00000024    $...     DCD    36

第1行,寄存器间接寻址,获取 _start 的地址,此时,r0 = 0x00000024。

第4行,此时,r0 = 0x00000024。

第7行,取得标号 _start 的绝对地址,这个绝对地址是在 link 的时候确定的。看上去这只是一个指令,但是它要占用 2 个 32bit 的空间,一条是指令,另一条是 _start 的数据。因为在编译的时候不能确定 _start 的值,而且也不能用 mov 指令来给 r0 赋一个 32bit 的常量,所以需要多出一个空间存放 _start 的真正数据,在这里就是 0x00000024。由此可以看出,这个是绝对的寻址,不管这段代码在什么地方运行,它的结果都是 r0 = 0x00000024。

原文来之:华清远见嵌入式学院

0 0
原创粉丝点击