Hvordan fungerer ldr-instruktionen på ARM?

ldr r0, #0x28 

Hvad giver instruktionen til ldr? Indlæser den en streng fra en offset? Hvordan kan jeg finde den streng / værdi, der faktisk er indlæst?

Kommentarer

  • er du sikker på, at den ' s #0x28 og ikke =#0x28?

Svar

LDR indlæser en 32-bit konstant (LDRH (halvord): 16 bit, LDRB (byte): 8 bit) fra hukommelsen i det angivne målregister (r0 i dit eksempel).

Da 32-bit konstanter ikke kan kodes i 32-bit opkoder (eller 16-bit til Thumb instruktioner), gemmer samleren konstanten i tekstsegmentet tæt på referenceinstruktionen og henviser derefter værdien ved hjælp af ( normalt) PC-relativ adressering, dvs. noget forskudt fra r15.

Således er ldr faktisk en pseudo-instruktion. Følgende kode

 .code 32 main: ldr r0, =0x12345678 bx lr 

oversættes af samleren til

00000000 <main>: 0: e51f0000 ldr r0, [pc, #-0] ; 8 <main+0x8> 4: e12fff1e bx lr 8: 12345678 .word 0x12345678 

Som du kan se, den konstante, der henvises til i den originale ldr-instruktion, lagres faktisk på adressen 0x8 i stedet for i selve instruktionen. Ldr-instruktionen på adresse 0 henviser derefter til denne værdi ved hjælp af pc-relativ adressering. Forskydningen til pcen er 0 (i stedet for 8), da den faktiske pc-værdi altid er adressen på den aktuelle instruktion + 8 – dette er en effekt af den tidlige ARM-processorrørledning, som skal bevares for kompatibilitet.

Svar

Dette kan simpelthen oversættes til:

r0 = 0x28; 

I ARM-samling markerer # de umiddelbare værdier, og r0, r1, … er registre. ldr instruktionen kan tage følgende syntaktiske former (din er første linje):

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 

Svar

ldr uden = laver pc-relative belastninger

Dette gælder både for etiketter og tal.

Men du vil selvfølgelig sjældent bruge numre direkte i din samling. Måske har du leveret noget adskillelse uden etiketter?

Begge følgende arbejder i GNU GAS ARMv8. Med en etiket:

 ldr x0, pc_relative_ldr b 1f pc_relative_ldr: .quad 0x123456789ABCDEF0 1: /* x0 == 0x123456789ABCDEF0 */ 

med en forskydning:

 ldr x0, 0x8 b 1f .quad 0x123456789ABCDEF0 1: /* x0 == 0x123456789ABCDEF0 */ 

Begge er ækvivalente. Samleren konverterer bare etiketten til den korrekte forskydning for dig.

GitHub opstrøms med påstande .

STR har ikke pc-relativ adressering som LDR i ARMv8, du skal bare beregne adressen i registre først: https://stackoverflow.com/questions/28638981/howto-write-pc-relative-adressing-on-arm-asm/54480999#54480999

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *