彙編指令-adr與ldr僞彙編區別

adr :相對尋址,與當前位置有關

ldr :絕對尋址,與當前位置無關

  在初始化SDRAM時就會用到adr,代碼如下:

 /*   初始化SDRAM       */
       ldr r0,=BWSCON                    //r0=SDRAM寄存器基地址,獲取絕對地址
       adr r1,SDRAM_CONFIG           //使用adr相對跳轉, r1=SDRAM_CONFIG地址
       add r2,r0,#(13*4)              
 
0:
       ldr r3,[r1],#4                      
       str r3,[r0],#4                      
       cmp r0,r2
       bne 0b                        
 
SDRAM_CONFIG:
    .long 0x22011110;     //BWSCON
    .long 0x00000700;     //BANKCON0
    .long 0x00000700;     //BANKCON1
    .long 0x00000700;     //BANKCON2
    .long 0x00000700;     //BANKCON3 
    .long 0x00000700;     //BANKCON4
    .long 0x00000700;     //BANKCON5
    .long 0x00018005;     //BANKCON6
    .long 0x00018005;     //BANKCON7
    .long 0x008C04F4;     //REFRESH
    .long 0x000000B1;     //BANKSIZE
    .long 0x00000030;     //MRSRB6
    .long 0x00000030;     //MRSRB7

  上面代碼中第3行之所以用到了 “ adr r1,SDRAM_CONFIG ”,是因爲SDRAM未初始化之前,不能使用絕對尋址,所以使用adr相對尋址.

  adr r1,SDRAM_CONFIG就相當於 ldr r1,=SDRAM_CONFIG
  通過以下實例:

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

  得出以下彙編(r0設爲0C008000):

0c008000 <_start-0x14>:
c008000: e59f000c ldr r0, [pc, #12] ; c008014 <_start>           //ldr指令(不帶=)  :  r0= c008014裏面內容= e1a00000 
c008004: e28f0008 add r0, pc, #8 ; 0x8                                  //adr指令:             r0=(當前PC值+8)+0x8=c008014
c008008: e59f0008 ldr r0, [pc, #8] ; c008018 <_start+0x4>     //ldr指令(帶=)  :   r0=c008018 裏面內容=0c008014 
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

  分析出:

ldr r0, _start 

  將內存地址 _start (c008014)裏的數據放入r0中。執行這個後,r0 = 0xe1a00000

adr r0, _start

  將 _start 的地址值(c008014)放入 r0中,但是請看反編譯的結果,它是與位置無關的。其實取得的時相對的位置。例如這段代碼在 0x0c008000 運行,那麼 adr r0, _start 得到 r0 = 0x0c008014;如果在地址 0 運行,就是 0x00000014 了。

ldr r0, =_start

  這個取得標號 _start 的絕對地址值(c008014)。這個絕對地址是在 link 的時候確定的。看上去這只是一個指令,但是它要佔用 2 個 32bit 的空間,一條是指令,另一條是 _start 的數據(因爲在編譯的時候不能確定 _start 的值,而且也不能用 mov 指令來給 r0 賦一個 32bit 的常量,所以需要多出一個空間存放 _start 的真正數據,在這裏就是 0x0c008014)。
  因此可以看出,這個是絕對的尋址,不管這段代碼在什麼地方運行,它的結果都是 r0 = 0x0c008014

結論:
對於adr r0,XXX 就相當於 ldr r0,=XXX ,通常用於SDRAM 未初始化之前用

發佈了76 篇原創文章 · 獲贊 1 · 訪問量 1855
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章