jal

jal

Assembly RISC-V Referência

lyszt.net aborda jal e outras instruções RISC-V com mais detalhes.

Formato de codificação

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

Descrição

jal chama uma função. Uma função é um bloco nomeado de instruções que pode ser executado a partir de vários lugares e então retornar, de modo que a lógica é escrita uma vez e usada em qualquer lugar. Chamar uma função exige duas coisas. O programa salta para onde a função está, e lembra de onde veio para voltar depois. jal faz as duas coisas, e seu nome significa jump and link.

O salto vai para um rótulo que marca a função. A parte link acontece antes do salto. jal salva o endereço da próxima instrução, a que vem logo após a chamada, em um registrador. A função usa esse endereço salvo para retornar.

Por convenção, o endereço salvo vai em um registrador chamado ra, de return address. A linha abaixo salta para a função square e deixa em ra o endereço para retornar.

jal ra, square

Quando a função termina, ela retorna saltando para o endereço em ra, que é o que a instrução ret faz. A abreviação usual para a mesma chamada é mostrada abaixo.

call square

O manual do RISC-V diz que o deslocamento do salto é contado em múltiplos de 2 bytes, estendido com sinal e somado ao endereço da instrução de salto. Isso dá um alcance de mais ou menos 1 MiB, onde um MiB é 1.048.576 bytes. jal armazena o endereço da instrução seguinte, que é pc mais 4, em rd. A convenção de chamada de software padrão usa x1 como registrador de endereço de retorno e x5 como registrador de link alternativo. As instruções de salto incondicional usam endereçamento relativo ao pc, o que dá suporte a código independente de posição, ou seja, código que funciona onde quer que seja carregado na memória.

Um jal sobrescreve ra com um novo endereço de retorno. Se uma função chama outra função, a chamada interna substitui o endereço salvo da externa. Uma função que faz suas próprias chamadas deve salvar ra primeiro e restaurá-lo antes de retornar. O exemplo chama square e deixa o endereço de retorno em ra.

Exemplo

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