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
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
#0x28
og ikke=#0x28
?