Инструкция LDR как прыжок в память

#assembly #arm #cortex-m

Вопрос:

Я смотрю на ассемблерный код и нашел одну инструкцию, назначение которой я не понимаю ldr PC, r1 . Насколько я понимаю, это выполняет переход в память к значению, содержащемуся по адресу, указанному r1. Почему бы не использовать инструкцию B или BL? Будет ли инструкция LDR останавливать конвейер? И из чистого любопытства, что может произойти, если трубопровод не заглохнет?

Комментарии:

1. Я предполагаю, что это ldr pc, [r1] так . Как таковой, это косвенный переход через указатель в памяти. Ни b то, ни bl другое не может этого сделать.

2. это может быть mov pc, r1, один или другой ldr pc, [r1]

3. @Jester Извините, я пропустил ноль в конце, если это что-нибудь изменит — ldr PC, r1, 0

4. Я часто вижу это в компиляции случая переключения, используемой со смещением и сдвигом.

5. @Вы имеете в виду Крола ldr pc, [r1, #0] ? Это то же самое, что ldr pc, [r1]

Ответ №1:

Одна из причин заключается в том, что команды ветвления ARM не могут разветвляться на адрес, удаленный более чем на 4 килобайта от текущего счетчика программ. (Я не знаком с более новыми машинами на базе ARM, только Game Boy Advance, у него есть это ограничение, но я не уверен в m-Cortex)

Ответ №2:

Адреса глобальных функций находятся в таблице в памяти. Или может быть просто таблица адресов перехода.

     adr     r1, jumptable
    ldr     r2, [r1, r12, lsl #2]!
    blx     r2

    ldr     pc, [r1, #4]



jumptable:
    .word   0x80000000
    .word   0x800000c0
    .word   0x800000e0
 

Описанная выше процедура сначала разветвляется (со ссылкой) на r12 подпрограмму th, а затем (без ссылки) на следующую в таблице по возвращении.


Большинство функций начинаются с сохранения регистров при вызове:

 push    {r4-r10, lr}
 

затем восстановите регистры при возврате по:

 pop     {r4-r10, lr}
 

и, наконец, вернитесь к звонящему по:

 bx      lr
 

Но более вероятно, что восстановление и фактическое возвращение будут объединены, как:

 pop     {r4-r10, pc}