歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

ARM下書寫位置無關的代碼

位置無關代碼,即該段代碼無論放在內存的哪個地址,都能正確運行。究其原因,是因為代碼裡
沒有使用絕對地址,都是相對地址。

位置無關的寫法:

(1) B指令

B指令接受一個相對地址,因此在匯編裡用B跳轉到一個標號時,實際編譯的結果是一個相對跳轉。
相對地址有個范圍限制,即目標不能太遠,一般目標放在同一個文件裡是肯定可以的。
_start:
    b  _reset
_reset:
      ...

(2) BL

BL用於調用函數,也是一個相對跳轉

(3) ADR

獲取標號的地址,在編譯時會使用PC+偏移的方式得到該位置的地址。例如,當TEXT_BASE是0時
SMRDATA可能被放在0x100的位置,當TEXT_BASE為0x30000000時放在0x30000100的位置。使用ADR
總能獲取正確的位置,與程序的加載地址無關。
    ADR R0, SMRDATA
SMRDATA:
    .word  0x22111120
    .word  0x00002F50
    .word  0x00000700
(相應的, LDR Rn, =LABEL是位置相關的)

(4) LDR

當加標號時,LDR可以用於偽指令,也可以真指令。
真指令: (標號前不加=號,表示取標號處的值)
    LDR R0,  SDRDATA
實際被編譯為LDR R0, [PC, #NN],其中NN是目標的相對距離

偽指令: (標號前加=號,取標號的地址)
    LDR R0, = SDRDATA
實際編譯的時候的時候,會在某位置存處SDRDATA的值,然後用一個LDR取出來。
顯然,用LDR時,加不加=號有很大區別。
無=號:取該標號處的值,位置無關
有=號:取該標號的地址,位置相關

舉例分析

例1:中斷向量跳轉

_start:    
    b       reset
    ldr    pc, _undefined_instruction
    ldr    pc, _software_interrupt
    ldr    pc, _prefetch_abort
    ldr    pc, _data_abort
    ldr    pc, _not_used
    ldr    pc, _irq
    ldr    pc, _fiq

_undefined_instruction:    .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq
其中,
ldr pc, _irq,由於沒加=號,表示取值_irq處的值放在pc裡 (位置無關)
_irq:  .word irq ,表示_irq存放的值是irq的絕對地址(位置有關)
Copyright © Linux教程網 All Rights Reserved