參考:
b指令是相對跳轉指令,是根據當前pc暫存器的值加上偏移來實現跳轉的,所以它和**在記憶體中的位置無關。
但是我們在檢視彙編檔案的時候,經常會有種錯覺,它好像是按絕對位址進行跳轉的,因為b指令的形式是 「b label",即跳轉到label處進行執行,label這個標籤明顯是絕對位址啊。其實在彙編語句翻譯成機器碼時會將語句翻譯成按相對位址進行定址。計算方式是:
指令所要跳轉到的標號位址=執行這條指令時pc的值(這條指令的位址值+8,預取指的原因)+機器碼中的立即數*4
彙編檔案head.s
.global _start
.text
_start:
b reset
b aa
b bb
b 0x30
reset:
.space 8,0xab
aa: .word 0xdeadbeef
.space 8,0xab
bb: .word 0xdeadbeef
.word 0xdeadbeef
.end
objdump得到:
disassembly of section .text:
00000000 <_start>:
0: ea000002 b 10
4: ea000003 b 18
8: ea000005 b 24
c: ea000004 b 24
00000010 :
10: abababab .word 0xabababab
14: abababab .word 0xabababab
00000018 :
18: deadbeef .word 0xdeadbeef
1c: abababab .word 0xabababab
20: abababab .word 0xabababab
00000024 :
24: deadbeef .word 0xdeadbeef
28: deadbeef .word 0xdeadbeef
b reset 也就是 b 10,對應的機器碼是 ea000002,其中ea**b指令,2為機器碼中的要跳轉的偏移,目標位址00000010是通過pc+2*4得到的,此時pc = 00000008 ,目標位址 = pc + 2 * 4 = 8+8 = 16= 0x10,正好是reset標籤處的位址。
arch/arm/kernel/head-common.s檔案
__lookup_processor_type:
adr r3, __lookup_processor_type_data
ldmia r3,
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldmia r5, @ value, mask
and r4, r4, r9 @ mask wanted bits
teq r3, r4
beq 2f
add r5, r5, #proc_info_sz @ sizeof(proc_info_list)
cmp r5, r6
blo 1b
mov r5, #0 @ unknown processor
2: ret lr
第10行 beq 2f ,向前跳轉到標籤2處,2f中的f其實是forward的意思;
第13行 blo 1b,向後跳轉到標籤1處,1b中的b是backward的意思。
其中1和2是區域性標籤。
arm中的飽和指令
armv6 及更高版本中推出了飽和指令 ssat 和 usat,ssat16 和 usat16 有符號飽和到任何位位置和無符號飽和到任何位位置,可選擇在飽和前進行移位。ssat可將有符號值飽和到有符號範圍內。usat可將有符號值飽和到無符號範圍內。語法 oprd,sat,rm其中 op 是ssat或...
ARM中的STM LDM指令
stm ldm是批量傳輸資料的指令,這裡要說明的是 15 0 register list代表了16個暫存器,傳輸資料的時候r15始終是最後傳輸的,按照從r0到r15的順序,r15始終在高位址。遞增傳輸倒好理解,關鍵是遞減傳輸,2440的datasheet令我費解,看看datasheet裡的一張圖 假...
ARM中的跳轉指令
arm中的跳轉指令 arm中b bl bx blx指令的區別 用於實現程式流程的跳轉,在arm程式中有兩種方法可以實現程式流程的跳 使用專門的跳轉指令 直接向程式計數器pc寫入跳轉位址值 通過向程式計數器pc寫入跳轉位址值,可以實現在4gb的位址空間中的任意跳轉,在跳轉之前結合使用 mov lr,p...