Hur fungerar ldr-instruktionen på ARM?

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

  • är du säker på att den ' s #0x28 och inte =#0x28?

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

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *