Skip to content

estrutura do assembly

Diogo Valadares Reis dos Santos edited this page Aug 26, 2025 · 2 revisions

[English]

[← Página Anterior | Próxima Página →]

Estrutura do Assembly

Antes de começar seus próprios programas, é recomendado instalar o Notepad++ para destacar a sintaxe, conforme descrito nos primeiros passos

Para criar um novo programa para a arquitetura, você precisará criar um arquivo em uma pasta visível para o assembler. Neste repositório, essa pasta está localizada em DRISC Programs/src/. O arquivo também deve ter a extensão .dasm.

Após abrir o arquivo com o Notepad++, será necessário alterar manualmente o idioma para dasm em Language > dasm, e então você estará pronto para começar a escrever seu programa.

Sintaxe

A sintaxe usada no Assembly DRISC-V é semelhante a outros formatos de assembly RISC-V, mas há algumas diferenças importantes.

Primeiro, você não precisa usar vírgulas (,) entre os parâmetros das instruções. Os parâmetros são simplesmente separados por espaços. Além disso, os offsets são declarados após o registrador que contém o endereço, como mostrado na lista de instruções abaixo.

Há também pequenas diferenças na forma como os rótulos (labels) e endereços de variáveis são referenciados, além de outras particularidades da linguagem.

Para escrever uma instrução, normalmente você começa com seu nome, seguido pelos parâmetros. Por exemplo:

sw s0 s1 3

Na sintaxe DRISC-V, o valor imediato sempre é o último parâmetro, enquanto os demais são quase sempre registradores.

Lista de Instruções

A tabela a seguir contém o nome de todas as instruções disponíveis no assembler atual, junto com os parâmetros necessários para cada uma funcionar corretamente. Os parâmetros que você encontrará são:

rd, rs, rs1 e rs2: São, respectivamente, os registradores de destino e origem. Você pode usar os nomes ABI ou simplesmente xN, onde N é o número do registrador.

imm: Valor imediato, que pode ser escrito em hexadecimal (ex: 0xAf24) ou como um número decimal com sinal. Também é possível usar rótulos ou endereços de variáveis.

label: Um rótulo é um marcador de endereço no seu código. Para definir um, escreva :Nome_Do_Label em uma linha vazia. Para usá-lo como parâmetro, escreva da mesma forma. Para variáveis (que serão discutidas depois), use . em vez de :.

offset: Semelhante ao imm, mas esse valor será somado a um registrador que contém um endereço. Você pode pensar nisso como um índice de array em C (array[indice]).

csr: Pode ser o nome de qualquer CSR listado aqui.

💡 Dica para Ler Instruções

Ao ler os nomes das instruções, certos sufixos podem dar pistas sobre seu comportamento:

  • I: Geralmente significa Immediate. Refere-se a uma instrução OP-IMM, que usa um valor imediato como um dos operandos.
  • U: Normalmente indica Unsigned. O último bit é tratado como um dígito regular, não como sinal.
  • Z: Refere-se a Zero, indicando que um registrador ou valor deve ser zero.
  • B: Byte (8 bits).
  • H: Half-word (16 bits).
  • W: Word (32 bits).
  • GE, GT, LE, LT: São, respectivamente, maior ou igual, maior que, menor ou igual, menor que.

Entender esses sufixos ajuda a identificar rapidamente o propósito e o comportamento das instruções no assembler.


Instruções Diversas

Instrução Parâmetros Comportamento Observações
LUI rd imm rd <= imm << 12 Carrega imediato superior
LI rd imm rd <= imm (32 bits) Carrega imediato (pseudo)
LA rd label rd <= label (32 bits) Carrega endereço (pseudo)
AUIPC rd imm rd <= PC + (imm << 12) Soma imediato superior ao PC
NOP Sem operação
MV rd rs rd <= rs Move registrador (pseudo)
ECALL Chamada de ambiente Dispara chamada de sistema
EBREAK Ponto de interrupção Dispara exceção de breakpoint
MRET PC < mepc; p < pp Retorna do tratador de exceção ou muda para modo usuário

Saltos Incondicionais

Instrução Parâmetros Comportamento Observações
J label PC <= label Salto incondicional
JUMP label PC <= label Igual ao J
JR rs PC <= rs Salto para registrador
JAL rd label rd <= Próximo PC ; PC <= label Salto com link
JALR rd rs1 imm rd <= Próximo PC ; PC <= rs1 + imm Salto com link via registrador
CALL label ra <= Próximo PC ; PC <= label Chamada de subrotina
RET PC <= ra Retorno de subrotina

Desvios Condicionais

Instrução Parâmetros Comportamento
BEQ rs1 rs2 label se(rs1 == rs2) PC <= label
BNE rs1 rs2 label se(rs1 != rs2) PC <= label
BLE rs1 rs2 label se(rs1 <= rs2) PC <= label
BLT rs1 rs2 label se(rs1 < rs2) PC <= label
BGE rs1 rs2 label se(rs1 >= rs2) PC <= label
BGT rs1 rs2 label se(rs1 > rs2) PC <= label
BLEU rs1 rs2 label se(rs1 <= rs2) (sem sinal) PC <= label
BLTU rs1 rs2 label se(rs1 < rs2) (sem sinal) PC <= label
BGEU rs1 rs2 label se(rs1 >= rs2) (sem sinal) PC <= label
BGTU rs1 rs2 label se(rs1 > rs2) (sem sinal) PC <= label
BEQZ rs1 label se(rs1 == 0) PC <= label
BNEZ rs1 label se(rs1 != 0) PC <= label
BLTZ rs1 label se(rs1 < 0) PC <= label
BGEZ rs1 label se(rs1 >= 0) PC <= label
BGTZ rs1 label se(rs1 > 0) PC <= label
BLEZ rs1 label se(rs1 <= 0) PC <= label

Carregamento e Armazenamento

Instrução Parâmetros Comportamento Observações
LB rd rs1 offset rd <= sinal_ext(mem[rs1 + offset]) Carrega Byte
LBU rd rs1 offset rd <= zero_ext(mem[rs1 + offset]) Byte sem sinal
LH rd rs1 offset rd <= sinal_ext(mem[rs1 + offset]) Carrega Half
LHU rd rs1 offset rd <= zero_ext(mem[rs1 + offset]) Half sem sinal
LW rd rs1 offset rd <= mem[rs1 + offset] Carrega Word
SB rs2 rs1 offset mem[rs1 + offset] <= rs2 (byte) Armazena Byte
SH rs2 rs1 offset mem[rs1 + offset] <= rs2 (halfword) Armazena Half
SW rs2 rs1 offset mem[rs1 + offset] <= rs2 (word) Armazena Word

Aritmética Inteira

Nota: Embora as instruções de divisão e resto sejam suportadas pelo assembler, a versão atual do DRISC-V não as implementa e pode apresentar comportamento indefinido.

Instrução Parâmetros Comportamento
ADDI rd rs1 imm rd <= rs1 + imm
ADD rd rs1 rs2 rd <= rs1 + rs2
SUB rd rs1 rs2 rd <= rs1 - rs2
MUL rd rs1 rs2 rd <= rs1 * rs2
MULH rd rs1 rs2 rd <= parte_alta(rs1 × rs2) com sinal
MULHSU rd rs1 rs2 rd <= parte_alta(rs1 × rs2) sinal × sem sinal
MULHU rd rs1 rs2 rd <= parte_alta(rs1 × rs2) sem sinal
DIV rd rs1 rs2 rd <= rs1 / rs2
DIVU rd rs1 rs2 rd <= rs1 / rs2 (sem sinal)
REM rd rs1 rs2 rd <= rs1 % rs2
REMU rd rs1 rs2 rd <= rs1 % rs2 (sem sinal)
INC rd imm rd <= rd + imm
DEC rd imm rd <= rd - imm

Operações Lógicas e Bit a Bit

Instrução Parâmetros Comportamento
ANDI rd rs1 imm rd <= rs1 & imm
ORI rd rs1 imm rd <= rs1 | imm
XORI rd rs1 imm rd <= rs1 ^ imm
AND rd rs1 rs2 rd <= rs1 & rs2
OR rd rs1 rs2 rd <= rs1 | rs2
XOR rd rs1 rs2 rd <= rs1 ^ rs2
NOT rd rs rd <= ~rs

Comparações

Instrução Parâmetros Comportamento
SLTI rd rs1 imm rd <= (rs1 < imm) ? 1 : 0
SLTIU rd rs1 imm rd <= (rs1 < imm) ? 1 : 0 (sem sinal)
SLT rd rs1 rs2 rd <= (rs1 < rs2) ? 1 : 0
SLTU rd rs1 rs2 rd <= (rs1 < rs2) ? 1 : 0 (sem sinal)
SGTI rd rs1 imm rd <= (rs1 > imm) ? 1 : 0
SGTIU rd rs1 imm rd <= (rs1 > imm) ? 1 : 0 (sem sinal)
SGT rd rs1 rs2 rd <= (rs1 > rs2) ? 1 : 0
SGTU rd rs1 rs2 rd <= (rs1 > rs2) ? 1 : 0 (sem sinal)
SEQZ rd rs rd <= (rs == 0) ? 1 : 0
SNEZ rd rs rd <= (rs != 0) ? 1 : 0
SLTZ rd rs rd <= (rs < 0) ? 1 : 0
SGTZ rd rs rd <= (rs > 0) ? 1 : 0

Deslocamentos (Shifts)

Instrução Parâmetros Comportamento
SLLI rd rs1 imm rd <= rs1 << imm
SRLI rd rs1 imm rd <= rs1 >> imm
SRAI rd rs1 imm rd <= rs1 >>> imm
SLL rd rs1 rs2 rd <= rs1 << rs2
SRL rd rs1 rs2 rd <= rs1 >> rs2
SRA rd rs1 rs2 rd <= rs1 >>> rs2

Extensões de Valor

Instrução Parâmetros Comportamento
SEXT.B rd rs Extensão de sinal (byte)
SEXT.H rd rs Extensão de sinal (halfword)
ZEXT.B rd rs Extensão com zero (byte)
ZEXT.H rd rs Extensão com zero (halfword)

Acesso a CSR

Instrução Parâmetros Comportamento
CSRR rd csr rd <= CSR[csr]
CSRW csr rs CSR[csr] <= rs
CSRS csr rs CSR[csr]
CSRC csr rs CSR[csr] &= ~rs
CSRRW rd csr rs rd <= CSR[csr]; CSR[csr] <= rs
CSRRS rd csr rs rd <= CSR[csr]; CSR[csr]
CSRRC rd csr rs rd <= CSR[csr]; CSR[csr] &= ~rs
CSRWI csr imm CSR[csr] <= imm
CSRSI csr imm CSR[csr]
CSRCI csr imm CSR[csr] &= ~imm
CSRRWI rd csr imm rd <= CSR[csr]; CSR[csr] <= imm
CSRRSI rd csr imm rd <= CSR[csr]; CSR[csr]
CSRRCI rd csr imm rd <= CSR[csr]; CSR[csr] &= ~imm

Clone this wiki locally