jal

jal

Ensamblador RISC-V Referencia

lyszt.net cubre jal y otras instrucciones RISC-V con más detalle.

Formato de codificación

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

Descripción

jal llama a una función. Una función es un bloque de instrucciones con nombre que puede ejecutarse desde varios lugares y luego retornar, de modo que la lógica se escribe una vez y se usa en cualquier parte. Llamar a una función requiere dos cosas. El programa salta a donde está la función y recuerda de dónde vino para regresar después. jal hace ambas cosas, y su nombre significa jump and link (salto y enlace).

El salto va a una etiqueta que marca la función. La parte de enlace ocurre antes del salto. jal guarda la dirección de la siguiente instrucción, la que está justo después de la llamada, en un registro. La función usa esa dirección guardada para retornar.

Por convención, la dirección guardada va en un registro llamado ra, por return address (dirección de retorno). La línea de abajo salta a la función square y deja en ra la dirección a la que debe retornar.

jal ra, square

Cuando la función termina, retorna saltando a la dirección en ra, que es lo que hace la instrucción ret. La abreviatura habitual para la misma llamada se muestra abajo.

call square

El manual de RISC-V dice que el desplazamiento del salto se cuenta en múltiplos de 2 bytes, se extiende con signo y se suma a la dirección de la instrucción de salto. Esto da un rango de más o menos 1 MiB, donde un MiB es 1.048.576 bytes. jal almacena la dirección de la siguiente instrucción, que es pc más 4, en rd. La convención estándar de llamada de software usa x1 como registro de dirección de retorno y x5 como registro de enlace alternativo. Las instrucciones de salto incondicional usan direccionamiento relativo al pc, lo que admite código independiente de la posición, es decir, código que funciona dondequiera que se cargue en memoria.

Un jal sobrescribe ra con una nueva dirección de retorno. Si una función llama a otra función, la llamada interna reemplaza la dirección guardada de la externa. Una función que hace sus propias llamadas debe guardar ra primero y restaurarlo antes de retornar. El ejemplo llama a square y deja la dirección de retorno en ra.

Ejemplo

jal ra, square   # call square; ra holds the return address