Я пытаюсь понять, как правильно выйти из базовой программы в ARM, и я видел много кода, который использует PUSH {lr}
для сохранения адреса возврата вызывающей функции (при условии, что вызывающая сторона использовала BL
чтобы сохранить адрес возврата в lr
), чтобы затем позднее получить его и перейти к адресу возврата, используя POP {pc}
.У меня нет проблем, заставляя это работать с подпрограммами внутри функции main / _start, так как регистр lr
изменяется на BL
в этих случаях, но использование кода ниже значения, помещенного в стек, будет просто 0x0, вызывая ошибкупо возвращении.
.text
.global main
main:
PUSH {lr}
MOV r0, #42
POP {pc}
.end
Я запустил код с гораздо большим количеством внешних вещей, которые используют этот точный метод для возврата из основной функции без Segmentation Fault
, но когда я пытаюсь запустить эту базовую программу, используяОтладчик GDB очевидно, что lr
остается на нуле в первой строке main и, таким образом, выдает ошибку при возврате.По сути, мой вопрос заключается в том, как получить правильное значение для lr
, когда оно помещается в стек основной функции.
Я использовал
$ as -g ex.s -o ex && ld -e main ex.o -o ex
для компиляции исполняемого файла.
РЕДАКТИРОВАТЬ: я обнаружил, что использование
$ gcc ex.o -o ex
для связи с программой частично ответил на мой вопрос, глядя на вывод GDB, я обнаружил, что gcc
кажется инициализировать lr
с правильнымзначение, заставляющее пример программы завершиться нормально.Однако я все еще хотел бы знать, существует ли способ получения этого адреса при использовании ld
, как я делал раньше.