ldr r0, #0x28
Vad säger ldr
instruktion? Läser den in en sträng från någon offset? Hur kan jag hitta strängen / värdet som faktiskt har laddats?
Kommentarer
Svar
LDR laddar en 32-bitars konstant (LDRH (halvord): 16 bitar, LDRB (byte): 8 bitar) från minnet till det angivna målregistret (r0 i ditt exempel).
Eftersom 32-bitars konstanter inte kan kodas i 32-bitars opcodes (eller 16-bitars för Thumb-instruktioner), lagrar samlaren konstanten i textsegmentet nära referensinstruktionen och refererar sedan värdet med ( vanligtvis) PC-relativ adressering, dvs någon offset från r15.
Således är ldr faktiskt en pseudoinstruktion. Följande kod
.code 32 main: ldr r0, =0x12345678 bx lr
översätts av samlaren till
00000000 <main>: 0: e51f0000 ldr r0, [pc, #-0] ; 8 <main+0x8> 4: e12fff1e bx lr 8: 12345678 .word 0x12345678
Som du kan se, den konstant som refereras i den ursprungliga ldr-instruktionen lagras faktiskt vid adressen 0x8 istället för i själva instruktionen. Ldr-instruktionen vid adress 0 refererar sedan till detta värde med hjälp av PC-relativ adressering. PC-förskjutningen är 0 (istället för 8), eftersom det faktiska PC-värdet alltid är adressen till den aktuella instruktionen + 8 – detta är en effekt av den tidiga ARM-processorns pipeline som måste bevaras för kompatibilitet.
Svar
Detta kan enkelt översättas till:
r0 = 0x28;
I ARM-montering markerar #
de omedelbara värdena och r0
, r1
, … är register. Instruktionen ldr
kan ta följande syntaktiska former (din är första raden):
LDR{type}{cond} Rt, [Rn {, #offset}] ; immediate offset LDR{type}{cond} Rt, [Rn, #offset]! ; pre-indexed LDR{type}{cond} Rt, [Rn], #offset ; post-indexed LDRD{cond} Rt, Rt2, [Rn {, #offset}] ; immediate offset, doubleword LDRD{cond} Rt, Rt2, [Rn, #offset]! ; pre-indexed, doubleword LDRD{cond} Rt, Rt2, [Rn], #offset ; post-indexed, doubleword
Svara
ldr
utan =
belastar PC-relationer
Detta gäller både etiketter och siffror.
Men du kommer naturligtvis sällan att använda nummer direkt i din församling. Kanske har du tillhandahållit en del demontering utan etiketter?
Båda följande fungerar i GNU GAS ARMv8. Med en etikett:
ldr x0, pc_relative_ldr b 1f pc_relative_ldr: .quad 0x123456789ABCDEF0 1: /* x0 == 0x123456789ABCDEF0 */
med en förskjutning:
ldr x0, 0x8 b 1f .quad 0x123456789ABCDEF0 1: /* x0 == 0x123456789ABCDEF0 */
Båda är ekvivalenta. Monteraren råkar bara konvertera etiketten till rätt offset för dig.
GitHub uppströms med påståenden .
STR har inte PC-relativ adressering som LDR i ARMv8, du måste bara beräkna adressen i register först: https://stackoverflow.com/questions/28638981/howto-write-pc-relative-adressing-on-arm-asm/54480999#54480999
#0x28
och inte=#0x28
?