Como a instrução ldr funciona no ARM?

ldr r0, #0x28 

O que significa thw ldr instrução? Ele carrega uma string de algum deslocamento? Como posso encontrar a string / valor que está realmente carregado?

Comentários

  • tem certeza de que ' s #0x28 e não =#0x28?

Resposta

O LDR carrega uma constante de 32 bits (LDRH (meia palavra): 16 bits, LDRB (byte): 8 bits) da memória para o registro de destino especificado (r0 em seu exemplo).

Visto que constantes de 32 bits não podem ser codificadas em opcodes de 32 bits (ou 16 bits para instruções Thumb), o montador armazena a constante no segmento de texto perto da instrução de referência e, em seguida, faz referência ao valor usando ( geralmente) endereçamento relativo ao PC, ou seja, algum deslocamento de r15.

Assim, ldr é de fato uma pseudo instrução. O seguinte código

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

é traduzido pelo assembler em

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

Como você pode veja, a constante referenciada na instrução ldr original é de fato armazenada no endereço 0x8 em vez de na própria instrução. A instrução ldr no endereço 0 então faz referência a este valor usando o endereçamento relativo ao PC. O deslocamento para o PC é 0 (em vez de 8), uma vez que o valor real do PC é sempre o endereço da instrução atual + 8 – este é um efeito do pipeline do processador ARM anterior que deve ser preservado para compatibilidade.

Resposta

Isso pode ser simplesmente traduzido em:

r0 = 0x28; 

Na montagem do ARM, o # marca os valores imediatos e r0, r1, … são registros. A instrução ldr pode assumir as seguintes formas sintáticas (a sua é a primeira linha):

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 

Resposta

ldr sem = faz cargas relativas ao PC

Isso é verdadeiro para rótulos e números.

Mas é claro que você raramente usará números diretamente em sua montagem. Talvez você tenha fornecido alguma desmontagem sem rótulos?

Ambos os itens a seguir funcionam no GNU GAS ARMv8. Com um rótulo:

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

com um deslocamento:

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

Ambos são equivalentes. O montador simplesmente converte o rótulo no deslocamento correto para você.

GitHub upstream com asserções .

STR não tem endereçamento relativo ao PC como LDR no ARMv8, você só precisa calcular o endereço nos registros primeiro: https://stackoverflow.com/questions/28638981/howto-write-pc-relative-adressing-on-arm-asm/54480999#54480999

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *