jal

jal

Асемблер RISC-V Посилання

lyszt.net охоплює jal та інші інструкції RISC-V більш детально.

Формат кодування

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

Опис

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