天天看點

ARM彙編僞指令adr\ldr\adrl\nop

本文介紹的僞指令:

  • adr 小範圍的位址加載指令
  • ldr 大範圍的位址加載指令
  • adrl 中等範圍的位址加載指令
  • nop 空操作

僞指令說明

1、僞指令adr

彙編時adr僞指令通常被編譯器用ADD或SUB指令實作,若不能以一條指令替換則報錯。adr僞指令是基于pc或者寄存器的,基于pc時,該位址需和adr僞指令位于同一代碼段。

ADR僞指令格式 :ADR{cond} register, expr 位址表達式expr的取值範圍: 當位址值是位元組對齊時,其取指範圍為: +255 ~255B; 當位址值是字對齊時,其取指範圍為: -1020 ~ 1020B;   

2、僞指令ldr

彙編時ldr僞指令會被替換成一條合适的指令,使用mov或mvn指令替代它,否則放入文字池(比較深入沒看)

ARM中有一個ldr指令,還有一個ldr僞指令一般都使用ldr僞指令而不用ldr指令,不用考慮立即數是否合法。差別在于立即數前面的符号是#還是=。

ldr指令: ldr r0, #0xff

ldr僞指令: ldr r0, =0xf1 @涉及到合法/非法立即數,涉及到ARM文字池。編譯後被mov r0, #0xf1

重點:(為了更容易了解需要一點程式連結的知識)

adr和ldr的差别:ldr加載的位址在連結時确定,而adr加載的位址在運作時确定;是以我們可以通過adr和ldr加載的位址比較來判斷目前程式是否在連結時指定的位址運作。通過兩種僞指令實作方式大概可以看出兩種指令差别。這種差别在以下情況下應用時需要注意

首先說明兩個概念:

  •  a、位置無關編碼(PIC,position independent code):彙編源檔案編碼成二進制可執行程式時編碼方式與位置(記憶體位址)無關。
  • b、位置有關編碼:彙編源碼編碼成二進制可執行程式後和記憶體位址是有關的

連結位址和運作位址:可能相同也可能不同

對于位置有關代碼來說:最終執行時的運作位址和編譯連結時給定的連結位址必須相同,否則一定出錯。說一下原因,程式代碼運作時要從rom複制到ram中,這樣運作速度更快,但是這就有一個問題,那就是把代碼複制到ram的什麼位址去運作,位置無關碼則都可以,但使用了位置有關碼,那麼複制的目标位址必須與連接配接位址相同。

ldr作為僞指令進行跳轉時時就是位置有關碼。比如這一條ldr pc, =main 我們想通過向PC寄存器寫入 main函數位址來跳轉執行main函數,這就相當于向PC寫了一個常數,這個常數就是連接配接時main的位址。當在ram運作時位置發生偏移那麼這條指令就跳轉到錯誤位置,不會執行到main函數。

想反adr進行跳轉時就是位置無關碼,因為adr跳轉是以位址內插補點進行跳轉的,在ram運作時adr指令目前位址和目标位址可能與連接配接時不同,但是兩個位址之間的內插補點不會變是以,adr位置無關。

3、僞指令adrl

中等範圍的位址讀取 ADRL僞指令将基于PC相對偏移的位址值或基于寄存器相對偏移的位址值讀取到寄存器中,比ADR僞指令可以讀取更大範圍的位址。在彙編編譯器編譯源程式時,ADRL僞指令被編譯器替換成兩條合适的指令。若不能用兩條指令實作,則産生錯誤,編譯失敗。

ADRL僞指令格式:ADRL{cond} register, expr 位址表達式expr的取值範圍: 當位址值是位元組對齊時,其取指範圍為: -64K~64K; 當位址值是字對齊時,其取指範圍為: -256K~256K;

4、僞指令nop

格式:NOP

功能:延時;

特點:NOP僞指令在編譯時将會被替代成ARM中的空操作,比如MOV R0,R0指令等;