-
Notifications
You must be signed in to change notification settings - Fork 0
estrutura do assembly
[English]
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.
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.
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.
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çã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 |
| 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 |
| 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 |
| 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 |
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 |
| 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 |
| 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 |
| 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 |
| 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) |
| 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 |
-
- 1.1 Introduction
- 1.2 RISC-V Implementation
- 1.2.1 Available Instruction Set
- 1.2.2 Available Non-ISA Features
-
- 2.1 ALU
- 2.2 Register File
- 2.3 Program Counter
- 2.4 Input Buffer
- 2.5 RAM
- 2.6 Operation Controller
- 2.7 CSR Controller
-
- 3.1 Input Devices
- 3.1.1 Keyboard
- 3.1.2 Switches and Joystick
- 3.1.3 Random Number Generator
- 3.1.4 Real-Time Device
- 3.2 Output Devices
- 3.2.1 Screen
- 3.2.2 Terminal
- 3.2.3 Software Interrupt Register
- 3.1 Input Devices