#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}