ldr r0, #0x28
Hva instruerer ldr
? Laster den en streng fra en offset? Hvordan kan jeg finne strengen / verdien som faktisk er lastet?
Kommentarer
Svar
LDR laster en 32-bits konstant (LDRH (halvord): 16 bit, LDRB (byte): 8 bit) fra minnet i det spesifiserte målregisteret (r0 i ditt eksempel).
Siden 32-biters konstanter ikke kan kodes i 32-biters opkoder (eller 16-bits for tommelinstruksjoner), lagrer samleren konstanten i tekstsegmentet nær referanseinstruksjonen og refererer deretter verdien ved hjelp av vanligvis) PC-relativ adressering, dvs. noen forskyvning fra r15.
Dermed er ldr faktisk en pseudoinstruksjon. Følgende kode
.code 32 main: ldr r0, =0x12345678 bx lr
oversettes av 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, konstanten det refereres til i den opprinnelige ldr-instruksjonen er faktisk lagret på adressen 0x8 i stedet for i selve instruksjonen. Ldr-instruksjonen på adresse 0 refererer deretter til denne verdien ved hjelp av PC-relativ adressering. Forskyvningen til PC-en er 0 (i stedet for 8), siden den faktiske PC-verdien alltid er adressen til den gjeldende instruksjonen + 8 – dette er en effekt av den tidlige ARM-prosessorrørledningen som må bevares for kompatibilitet.
Svar
Dette kan enkelt oversettes til:
r0 = 0x28;
I ARM-samling markerer #
de umiddelbare verdiene og r0
, r1
, … er registre. Instruksjonen ldr
kan ha 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
uten =
laster PC relativt
Dette gjelder både etiketter og tall.
Men du vil selvfølgelig sjelden bruke nummer direkte i forsamlingen. Kanskje du har gitt noen demontering uten etiketter?
Begge følgende fungerer i GNU GAS ARMv8. Med en etikett:
ldr x0, pc_relative_ldr b 1f pc_relative_ldr: .quad 0x123456789ABCDEF0 1: /* x0 == 0x123456789ABCDEF0 */
med en forskyvning:
ldr x0, 0x8 b 1f .quad 0x123456789ABCDEF0 1: /* x0 == 0x123456789ABCDEF0 */
Begge er likeverdige. Samleren konverterer bare etiketten til riktig forskyvning for deg.
GitHub oppstrøms med påstander .
STR har ikke PC-relativ adressering som LDR i ARMv8, du må 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
?