Skip to content

Assembly Structure

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

[Português]

[← Previous Page | Next Page →]

Assembly Structure

Before beginning you own programs it is recommended to install Notepad++ for the syntax highlight as described in the first steps

To create a new program for the architecture, you will need to create a file on a folder visible to the assembler. In this repository, this folder is located at DRISC Programs/src/. The file also should have the .dasm extension.

After opening the file with Notepad++, you will need to manually change the language to dasm in Language > dasm and you are ready to begin writing your program.

Syntax

The syntax used in DRISC-V Assembly is similar to other RISC-V assembly formats, but there are a few key differences.

First, you are not required to use commas (,) between parameters in instructions. Parameters are simply separated by spaces. Additionally, offsets are declared after the register containing the address, as shown in the instruction list below.

There are also small differences in how labels and variable addresses are referenced, as well as in other assembly features.

To write an instruction, you typically start with its name, followed by its parameters. For example:

sw s0 s1 3

In DRISC-V syntax, the immediate value is always the last parameter, while the others are almost always registers.

Instruction List

The following instruction table contains the name of every instruction available in the current assembler, along with the parameters required for each to function properly. The parameters you will encounter are:

rd, rs, rs1, and rs2: These are, respectively, the destination and source registers. You can either use the ABI names for the registers or simply use xN, where N is the register number.

imm: This is an immediate value, which can be written as a hexadecimal (e.g., 0xAf24) or as a regular signed decimal integer. You may also use labels or variable addresses if needed.

label: A label is an address marker in your code. To define one, write :Name_Of_The_Label on an empty line. To use it as a parameter, write it the same way. For variables, which will be discussed later, use a . instead of a :.

offset: Similar to imm, but this value will be added to a register containing an address. You can think of it like an array index in C (array[index]).

csr: This can be the name of any CSR listed here.

💡 Tip for Reading Instructions

When reading instruction names, certain suffixes can give you clues about their behavior:

  • I: Usually stands for Immediate. It often refers to an OP-IMM instruction, meaning it uses an immediate value as one of its operands.
  • U: Typically means Unsigned. In this case, the last bit is treated as a regular digit rather than a sign bit.
  • Z: Refers to Zero, often indicating that a register or value is expected to be zero.
  • B: Stands for Byte (8 bits).
  • H: Stands for Half-word (16 bits).
  • W: Stands for Word (32 bits).
  • GE GT LE LT: Those are respectively greater equal, greater than, less equal and less than.

Understanding these suffixes can help you quickly identify the purpose and behavior of instructions in the assembler.

Misc Instructions

Instruction Parameters Behavior Notes
LUI rd imm rd <= imm << 12 Load upper immediate
LI rd imm rd <= imm(32 bit) Load immediate (pseudo)
LA rd label rd <= label(32 bit) Load address (pseudo)
AUIPC rd imm rd <= PC + (imm << 12) Add upper immediate to PC
NOP No operation
MV rd rs rd <= rs Move register (pseudo)
ECALL Environment call Triggers a System call
EBREAK Breakpoint Triggers a Breakpoint exception
MRET PC < mepc; p < pp Used to return from the trap Handler or to go to user mode

Unconditional Jump Instructions

Instruction Parameters Behavior Notes
J label PC <= label Unconditional jump
JUMP label PC <= label Same as J
JR rs PC <= rs Jump to register
JAL rd label rd <= Next PC ; PC <= label Jump and link
JALR rd rs1 imm rd <= Next PC ; PC <= rs1 + imm Jump and link register
CALL label ra <= Next PC ; PC <= label Call subroutine
RET PC <= ra Return from subroutine

Branches

Instruction Parameters Behavior
BEQ rs1 rs2 label if(rs1 == rs2) PC <= label
BNE rs1 rs2 label if(rs1 != rs2) PC <= label
BLE rs1 rs2 label if(rs1 <= rs2) PC <= label
BLT rs1 rs2 label if(rs1 < rs2) PC <= label
BGE rs1 rs2 label if(rs1 >= rs2) PC <= label
BGT rs1 rs2 label if(rs1 > rs2) PC <= label
BLEU rs1 rs2 label if(rs1 <= rs2) (unsigned) PC <= label
BLTU rs1 rs2 label if(rs1 < rs2) (unsigned) PC <= label
BGEU rs1 rs2 label if(rs1 >= rs2) (unsigned) PC <= label
BGTU rs1 rs2 label if(rs1 > rs2) (unsigned) PC <= label
------------- --------------------- ---------------------------------------------
BEQZ rs1 label if(rs1 == 0) PC <= label
BNEZ rs1 label if(rs1 != 0) PC <= label
BLTZ rs1 label if(rs1 < 0) PC <= label
BGEZ rs1 label if(rs1 >= 0) PC <= label
BGTZ rs1 label if(rs1 > 0) PC <= label
BLEZ rs1 label if(rs1 <= 0) PC <= label

Loads & Stores

Instruction Parameters Behavior Notes
LB rd rs1 offset rd <= sign_extend(mem[rs1 + offset]) Load Byte
LBU rd rs1 offset rd <= zero_extend(mem[rs1 + offset]) Load Byte Unsigned
LH rd rs1 offset rd <= sign_extend(mem[rs1 + offset]) Load Half
LHU rd rs1 offset rd <= zero_extend(mem[rs1 + offset]) Load Half Unsigned
LW rd rs1 offset rd <= mem[rs1 + offset] Load Word
SB rs2 rs1 offset mem[rs1 + offset] <= rs2 (byte) Store Byte
SH rs2 rs1 offset mem[rs1 + offset] <= rs2 (halfword) Store Half
SW rs2 rs1 offset mem[rs1 + offset] <= rs2 (word) Store Word

Integer Arithmetic

Note: Although Division and Remainder instructions are supported by the assembler, the current version of DRISC-V do not support it and may have undefined behavior.

Instruction Parameters Behavior
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 <= signed_high(rs1 × rs2)
MULHSU rd rs1 rs2 rd <= signed_unsigned_high(rs1 × rs2)
MULHU rd rs1 rs2 rd <= unsigned_high(rs1 × rs2)
DIV rd rs1 rs2 rd <= rs1 / rs2
DIVU rd rs1 rs2 rd <= rs1 / rs2 (unsigned)
REM rd rs1 rs2 rd <= rs1 % rs2
REMU rd rs1 rs2 rd <= rs1 % rs2 (unsigned)
INC rd imm rd <= rd + imm
DEC rd imm rd <= rd - imm

Bitwise & Logic

Instruction Parameters Behavior
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

Comparisons

Instruction Parameters Behavior
SLTI rd rs1 imm rd <= (rs1 < imm) ? 1 : 0
SLTIU rd rs1 imm rd <= (rs1 < imm) ? 1 : 0 unsigned
SLT rd rs1 rs2 rd <= (rs1 < rs2) ? 1 : 0
SLTU rd rs1 rs2 rd <= (rs1 < rs2) ? 1 : 0 unsigned
SGTI rd rs1 imm rd <= (rs1 > imm) ? 1 : 0
SGTIU rd rs1 imm rd <= (rs1 > imm) ? 1 : 0 unsigned
SGT rd rs1 rs2 rd <= (rs1 > rs2) ? 1 : 0
SGTU rd rs1 rs2 rd <= (rs1 > rs2) ? 1 : 0 unsigned
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

Shifts

Instruction Parameters Behavior
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

Extension

Instruction Parameters Behavior
SEXT.B rd rs sign-extend byte
SEXT.H rd rs sign-extend halfword
ZEXT.B rd rs zero-extend byte
ZEXT.H rd rs zero-extend halfword

CSR Access

Instruction Parameters Behavior
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] <= rs
CSRRS rd csr rs rd <= CSR[csr]
CSRRC rd csr rs rd <= 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] <= imm
CSRRSI rd csr imm rd <= CSR[csr]
CSRRCI rd csr imm rd <= CSR[csr] &= ~imm

Clone this wiki locally