adr与ldr的区别

adr与ldr r0, =label的区别:
adr 和 ldr r0, =label(这里不包括ldr的一般用法)都是pseudo-instruction
adr r0, label与ldr r0, =label实际上实现的功能都是一样儿的,都是将label的地址存放到r0中,但是由于adr中用的是相对地址且使用一个汇编指令完成,故其寻址范围限制在4k的范围内。但是ldr则不同,由于其使用了literal pools,寻址范围可以在4G的任意范围(但是切记literal pools的位置仍然要在4k之内)。如果说两者之间有什么不同的话,那就是:使用ldr要比使用adr浪费一些存储空间(如果label距离PC不是很远的情况下,使用adr是合理的)。

使用arm的启动代码2440init.s来举例如下:
代码未作任何修改的代码如下:
copy_proc_beg
        adr        r0, ResetEntry
        ldr        r2, BaseOfROM
        cmp        r0, r2
        ldreq      r0, TopOfROM
        beq        InitRam      
        ldr        r3, TopOfROM
其反汇编结果如下:
   copy_proc_beg
        0x00000268:    e24f0f9c    ..O.    SUB      r0,pc,#0x270 ; #0
        0x0000026c:    e59f2140    @!..    LDR      r2,0x3b4
        0x00000270:    e1500002    ..P.    CMP      r0,r2
        0x00000274:    059f013c    <...    LDREQ    r0,0x3b8
        0x00000278:    0afffffe    ....    BEQ      InitRam  ; 0x298
        0x0000027c:    e59f3134    41..    LDR      r3,0x3b8
可见此时r0的值正好是(pc+8-270)=0x0(至于这里为什么加8请看后面),即ResetEntry的位置。
将adr r0, ResetEntry改写成ldr r0, =ResetEntry后代码如下:
copy_proc_beg
        ldr            r0, =ResetEntry
        ldr            r2, BaseOfROM
        cmp        r0, r2
        ldreq       r0, TopOfROM
        beq         InitRam      
        ldr            r3, TopOfROM
反汇编结果如下:
   copy_proc_beg
        0x00000268:    e59f00f0    ....    LDR      r0,0x360
        0x0000026c:    e59f2144    D!..    LDR      r2,0x3b8
        0x00000270:    e1500002    ..P.    CMP      r0,r2
        0x00000274:    059f0140    @...    LDREQ    r0,0x3bc
        0x00000278:    0afffffe    ....    BEQ      InitRam  ; 0x298
        0x0000027c:    e59f3138    81..    LDR      r3,0x3bc
可见这里是将0x360处的值赋给了r0,而0x360处在literal pools中,如下:
    $d(表示literal pools位置)
        0x00000328:    4a000008    ...J    DCD    1241513992
        0x0000032c:    4a00001c    ...J    DCD    1241514012
        0x00000330:    00007fff    ....    DCD    32767
        0x00000334:    4c000014    ...L    DCD    1275068436
        0x00000338:    4c000008    ...L    DCD    1275068424
        0x0000033c:    00038022    "...    DCD    229410
        0x00000340:    4c000004    ...L    DCD    1275068420
        0x00000344:    0005c011    ....    DCD    376849
        0x00000348:    560000b4    ...V    DCD    1442840756
        0x0000034c:    56000050    P..V    DCD    1442840656
        0x00000350:    56000058    X..V    DCD    1442840664
        0x00000354:    56000054    T..V    DCD    1442840660
        0x00000358:    000055aa    .U..    DCD    21930
        0x0000035c:    00000268    h...    DCD    616
        0x00000360:    00000000    ....    DCD    0
        0x00000364:    000002c8    ....    DCD    712
        0x00000368:    00000000    ....    DCD    0
        0x0000036c:    000000d8    ....    DCD    216
        0x00000370:    33ff5c00    .\.3    DCD    872373248
        0x00000374:    33ff6000    .`.3    DCD    872374272
        0x00000378:    33ff7000    .p.3    DCD    872378368
        0x0000037c:    33ff8000    ...3    DCD    872382464
        0x00000380:    33ff5800    .X.3    DCD    872372224
此处的值正好位0x0,即ResetEntry的位置。
在程序的423行,可以看到有一个LTORG伪指令,正是由于这个原因,编译器才会在0x00000328位置开始建立literal pools。有关literal pools可以参考http://blog.csdn.net/caimingda1987/article/details/6662893




前面提到pc指针默认加8的原因如下(转载):


2440是三级流水线结构,下面来讲讲为什么三级流水线,故名思义,就是一个时刻做三件事情,对于2440来说,那就是取指,译码,执行
取指 译码 执行。。。
   取指 译码 执行。。。
             取指 译码 执行。。。
那么问一个问题,PC究竟是指向取指呢,译码呢,还是执行,由此便带来一个问题,当前指令执行的时候,PC的值已经不是当前指令所在的地址了,而是
当前地址+8
   0x00000000
   0x00000004        ---假设为当前执行的指令地址
   0x00000008
PC-> 0x0000000c        PC指向的是这儿

Comments

Popular posts from this blog

Basic understanding of TLS-PSK protocol

Differences between ASIC, ASSP and ASIP

Orthogonal instruction set