callпсевдо

call

псевдо
RISC-V Ассемблер Ссылка

lyszt.net охватывает call и другие инструкции RISC-V более подробно.

Описание

call запускает функцию и обрабатывает возврат. Он выполняет переход к функции и сохраняет адрес возврата в ra, что позволяет функции вернуться. Это псевдоинструкция, которая обычно разворачивается в инструкцию ниже.

jal ra, label

Когда функция находится слишком далеко, чтобы один переход мог до неё добраться, ассемблер подставляет более длинную последовательность, покрывающую это расстояние. Запись call с именем функции выражает намерение и оставляет выбор формы ассемблеру. Запись jal описывает переход и сохранение адреса возврата. Строка ниже вызывает функцию square.

call square

Вызов функции также требует соглашения о том, как информация передаётся между вызывающим и вызываемым. Это соглашение называется соглашением о вызовах. Вызывающий помещает входные данные функции в регистры аргументов, называемые a0, a1 и так далее, и читает результат из a0 после возврата функции. Обе стороны следуют одному и тому же правилу, поэтому код, написанный отдельно, всё равно работает вместе.

Каждый call перезаписывает ra. Функция, которая сама делает вызовы, сохраняет полученный ra перед их выполнением, а затем восстанавливает это значение перед собственным возвратом. Без этого адрес возврата внутреннего вызова заменяет внешний, и функция не может вернуться. Функции, которая ничего больше не вызывает, не нужно сохранять ra.

Руководство RISC-V утверждает, что стандартное программное соглашение о вызовах использует x1 в качестве регистра адреса возврата. jal достигает целей в пределах плюс-минус 1 МиБ, где 1 МиБ — это 1 048 576 байт. Более далёкая цель требует auipc, за которым следует jalr, достигающий любого места в 32-битном диапазоне адресов относительно pc.

Пример вызывает square с 6 в a0 и после этого находит 36 в a0. Аргумент входит, а результат выходит через соглашение.

Разворачивается в

jal ra, label

Ассемблер заменяет эту псевдоинструкцию реальной инструкцией или инструкциями, перечисленными выше.

Пример

call square      # jumps to square; ra holds the return address