jal
lyszt.net охватывает jal и другие инструкции RISC-V более подробно.
Формат кодирования
Описание
jal вызывает функцию. Функция — это именованный блок инструкций, который может запускаться из нескольких мест и затем возвращать управление, так что логика пишется один раз и используется где угодно. Для вызова функции нужны две вещи. Программа переходит туда, где находится функция, и запоминает, откуда она пришла, чтобы потом вернуться. jal делает и то и другое, а его название означает jump and link (переход и связывание).
Переход идёт к метке, обозначающей функцию. Часть со связыванием происходит до перехода. jal сохраняет адрес следующей инструкции, той, что идёт сразу после вызова, в регистре. Функция использует этот сохранённый адрес для возврата.
По соглашению сохранённый адрес помещается в регистр с именем ra, от return address (адрес возврата). Строка ниже выполняет переход к функции square и оставляет в ra адрес, по которому нужно вернуться.
jal ra, square
Когда функция завершается, она возвращает управление, переходя по адресу в ra, что и делает инструкция ret. Обычное сокращение для того же вызова показано ниже.
call square
Руководство RISC-V говорит, что смещение перехода считается в кратных 2 байтам величинах, расширяется со знаком и прибавляется к адресу инструкции перехода. Это даёт диапазон плюс-минус 1 MiB, где MiB — это 1 048 576 байт. jal сохраняет адрес следующей инструкции, то есть pc плюс 4, в rd. Стандартное программное соглашение о вызовах использует x1 как регистр адреса возврата и x5 как альтернативный регистр связи. Инструкции безусловного перехода используют адресацию относительно pc, что поддерживает позиционно-независимый код, то есть код, работающий там, куда он загружен в память.
jal перезаписывает ra новым адресом возврата. Если функция вызывает другую функцию, внутренний вызов заменяет сохранённый адрес внешнего. Функция, которая сама выполняет вызовы, должна сначала сохранить ra и восстановить его перед возвратом. Пример вызывает square и оставляет адрес возврата в ra.
Пример
jal ra, square # call square; ra holds the return address
