14 KiB
14 KiB
DSA Assembly Language Instruction Reference
Overview
This document provides a comprehensive reference for the DSA (Damn Simple Architecture) assembly language, including all hardware instructions and pseudo-instructions with their syntax variations and usage examples.
Calling Convention
| Step | Responsibility | Action | Description |
|---|---|---|---|
| 1 | Caller | Push arguments | Push exactly n arguments to the stack (in order, last argument pushed first) |
| 2 | Caller | Call function | Execute call namespace::function - this automatically pushes the return address (pcx) and jumps to the function |
| 3 | Function | Set up stack frame | Execute push bpr; mov spr, bpr to establish new stack frame |
| 4 | Function | Access arguments | Read arguments starting at spr+8 (first 3 args at offsets 8, 12, 16) |
| 5 | Function | Execute function | Perform the function's operations using the arguments |
| 6 | Function | Store return value | Write return value (if any) to spr+8 |
| 7 | Function | Restore stack frame | Execute mov bpr, spr; pop bpr to restore previous stack frame |
| 8 | Function | Return | Execute return pseudo-instruction to return to caller |
| 9 | Caller | Clean up stack | Pop exactly n arguments from the stack to clean up |
| 10 | Caller | Handle unused values | Use pop zero to discard any unused stack values if needed |
Notes:
- The namespace in step 2 is the name assigned in the
includestatement - The
callpseudo-instruction automatically handles return address management so long as the callee does not mess with the stack - Arguments are accessed by the callee using offsets from the base pointer (bpr)
Registers
| Register | Type | Description |
|---|---|---|
rg0-rgf |
General Purpose | General-purpose registers. |
acc |
Special | Accumulator for calculations and temporary storage - don't use this for variables as pseudo instructions may overwrite this implicitly! |
spr |
Special | Stack pointer |
bpr |
Special | Base pointer for stack frames |
ret |
Special | Return address register |
idr |
Privileged | Interrupt descriptor table address on-read/write: protection fault (unless in kernel mode) |
mmr |
Privileged | Hardware memory map table address on-read/write: protection fault (unless in kernel mode) |
zero |
Read-only | Always contains zero on-read: always returns zero on-write: value is voided |
pcx |
Read-only | Program counter on-write: protection fault |
noreg |
Placeholder | Indicates absence of register argument on-read/write: illegal instruction fault |
Hardware Instructions
Data Movement Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| MOV | src_reg, dest_reg |
Copy value from source to destination register |
| MOVS | src_reg, dest_reg |
Copy with sign extension |
Examples:
mov rg0, rg1 ; Copy rg0 to rg1
movs rg0, rg1 ; Copy rg0 to rg1 with sign extension
Memory Access Instructions
Load Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| LDB | base_reg, dest_reg [, offset]label, dest_reg [, offset] |
Load byte from memory |
| LDBS | base_reg, dest_reg [, offset]label, dest_reg [, offset] |
Load byte with sign extension |
| LDH | base_reg, dest_reg [, offset]label, dest_reg [, offset] |
Load half-word (16-bit) |
| LDHS | base_reg, dest_reg [, offset]label, dest_reg [, offset] |
Load half-word with sign extension |
| LDW | base_reg, dest_reg [, offset]label, dest_reg [, offset] |
Load word (32-bit) |
Examples:
; Direct register addressing
ldb rg0, rg1 ; Load byte from address in rg0
ldw rg0, rg1, 8 ; Load word from (rg0 + 8)
; Label addressing
ldb buffer, rg2 ; Load byte from label 'buffer'
ldw stack, bpr ; Load stack address into base pointer
Label Expansions:
; ldb buffer, rg2 expands to:
lli buffer, rg2 ; Load lower 16 bits of buffer address
lui buffer, rg2 ; Load upper 16 bits of buffer address
ldb rg2, rg2 ; Load byte from address in rg2
; ldw stack, bpr expands to:
lli stack, bpr ; Load lower 16 bits of stack address
lui stack, bpr ; Load upper 16 bits of stack address
ldw bpr, bpr ; Load word from address in bpr
Store Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| STB | src_reg, base_reg [, offset]src_reg, label [, offset] |
Store byte to memory |
| STH | src_reg, base_reg [, offset]src_reg, label [, offset] |
Store half-word to memory |
| STW | src_reg, base_reg [, offset]src_reg, label [, offset] |
Store word to memory |
Examples:
; Direct register addressing
stb rg0, rg1 ; Store byte from rg0 to address in rg1
stw rg0, rg1, 12 ; Store word to (rg1 + 12)
; Label addressing
stb acc, buffer ; Store byte from accumulator to 'buffer'
stw rg1, current ; Store word to 'current' variable
Label Expansions:
; stb acc, buffer expands to:
lli buffer, rgf ; Load lower 16 bits of buffer address
lui buffer, rgf ; Load upper 16 bits of buffer address
stb acc, rgf ; Store byte from acc to address in rgf
; stw rg1, current expands to:
lli current, rgf ; Load lower 16 bits of current address
lui current, rgf ; Load upper 16 bits of current address
stw rg1, rgf ; Store word from rg1 to address in rgf
Immediate Load Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| LLI | imm, dest_reg |
Load 16-bit immediate into lower 16 bits Clears upper 16 bits! |
| LUI | imm, dest_reg |
Load 16-bit immediate into upper 16 bits |
Usage
ensure that you always run Lli before Lui as Lli clears the upper 16 bits.
Examples:
lli 0x1234, rg0 ; Load 0x1234 into lower 16 bits of rg0
lui 0xABCD, rg0 ; Load 0xABCD into upper 16 bits of rg0
Jump Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| JMP | addr [, offset_reg]imm, offset_reg |
Unconditional jump |
| JEQ | addr [, offset_reg] |
Jump if equal flag set |
| JNE | addr [, offset_reg] |
Jump if not equal flag set |
| JGT | addr [, offset_reg] |
Jump if greater than flag set |
| JGE | addr [, offset_reg] |
Jump if greater or equal flags set |
| JLT | addr [, offset_reg] |
Jump if less than flag set |
| JLE | addr [, offset_reg] |
Jump if less or equal flags set |
Examples:
jmp start ; Jump to label 'start'
jmp 4, ret ; Jump to address (4 + ret register)
jeq end ; Jump to 'end' if equal flag set
jgt loop ; Jump to 'loop' if greater than flag set
Arithmetic Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| ADD | src1_reg, src2_reg, dest_reg |
Addition |
| SUB | src1_reg, src2_reg, dest_reg |
Subtraction |
| IADD | src_reg, imm [, dest_reg] |
Immediate addition |
| ISUB | src_reg, imm [, dest_reg] |
Immediate subtraction |
| INC | reg |
Increment register by 1 |
| DEC | reg |
Decrement register by 1 |
Examples:
add rg0, rg1, rg2 ; rg2 = rg0 + rg1
sub rg0, rg1, rg2 ; rg2 = rg0 - rg1
iadd rg0, 10 ; rg0 = rg0 + 10
// or using alternate syntax
addi rg0, 1 ; rg0 = rg0 + 1
inc rg0 ; rg0 = rg0 + 1
Bitwise Operations
| Mnemonic | Operands | Description |
|---|---|---|
| AND | src1_reg, src2_reg, dest_reg |
Bitwise AND |
| OR | src1_reg, src2_reg, dest_reg |
Bitwise OR |
| XOR | src1_reg, src2_reg, dest_reg |
Bitwise XOR |
| NOT | src_reg, dest_reg |
Bitwise NOT |
| NAND | src1_reg, src2_reg, dest_reg |
Bitwise NAND |
| NOR | src1_reg, src2_reg, dest_reg |
Bitwise NOR |
| XNOR | src1_reg, src2_reg, dest_reg |
Bitwise XNOR |
Examples:
and rg0, rg1, rg2 ; rg2 = rg0 & rg1
not rg0, rg1 ; rg1 = ~rg0
Shift Operations
| Mnemonic | Operands | Description |
|---|---|---|
| SHL | reg, shift_amount |
Shift left |
| SHR | reg, shift_amount |
Shift right |
Examples:
shl rg0, 2 ; Shift rg0 left by 2 bits
shr rg0, 3 ; Shift rg0 right by 3 bits
Comparison and Control
| Mnemonic | Operands | Description |
|---|---|---|
| CMP | reg1, reg2 |
Compare registers and set flags |
Examples:
cmp rg0, zero ; Compare rg0 with zero register
cmp rg1, rg2 ; Compare rg1 with rg2
System Instructions
| Mnemonic | Operands | Description |
|---|---|---|
| HLT | - | Halt processor execution |
| NOP | - | No operation |
| INT | interrupt_code |
Trigger interrupt |
| IRT | - | Return from interrupt |
Examples:
hlt ; Stop processor execution
int 0x21 ; Trigger interrupt 0x21
Pseudo-Instructions
Data Definition
| Mnemonic | Syntax | Description |
|---|---|---|
| DB | name: value1 [, value2, ...] |
Define bytes |
| DH | name: value1 [, value2, ...] |
Define half-words |
| DW | name: value1 [, value2, ...] |
Define words |
Examples:
db message: "Hello World", 0
dh numbers: 1000, 2000, 3000
dw stack: 0x10000
Memory Reservation
| Mnemonic | Syntax | Description |
|---|---|---|
| RESB | name: size |
Reserve bytes |
| RESH | name: size |
Reserve half-words |
| RESW | name: size |
Reserve words |
Examples:
resb buffer: 256 ; Reserve 256 bytes
resh array: 100 ; Reserve space for 100 half-words
resw heap: 1024 ; Reserve space for 1024 words
Stack Operations
| Mnemonic | Operands | Description |
|---|---|---|
| PUSH | reg |
Push register value onto stack |
| POP | reg |
Pop stack value into register |
Examples:
push rg0 ; Push rg0 value onto stack
pop ret ; Pop return address
Memory Access Shortcuts
| Mnemonic | Operands | Description |
|---|---|---|
| LWI | name, reg |
Load address into register |
Examples:
lwi string, rg1 ; Load address of 'string' into rg1
Function Control
| Mnemonic | Operands | Description |
|---|---|---|
| CALL | namespace::function |
Call a function with automatic return address management |
| RETURN | - | Return from a function to the caller |
Examples:
call print::print ; Call the print function from the print namespace
return ; Return from the current function
Module System
| Mnemonic | Syntax | Description |
|---|---|---|
| INCLUDE | module_name "path" |
Include module |
Examples:
include print "print.dsa"
include fib "fib.dsa"
Library Examples
Multiplication Library (multiply.dsa)
// multiply.dsa
// usage:
//
// include multiply "<relative path>"
//
// usage for multiply:
// push (arg1)
// push (arg0)
// call multiply::multiply
// pop (arg0)
// pop (arg1)
multiply:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // load op 1
ldw bpr, rg1, 12 // load op 2
lli 0, acc // initialize accumulator
start:
add acc, rg0, acc
dec rg1
cmp rg1, zero
jgt start
end:
stw acc, bpr, 8 // store result for caller
mov bpr, spr
pop bpr
return
Print Library (print.dsa)
// print.dsa
// usage:
//
// include print "<relative path>"
//
// usage for print:
// push (register containing address of string)
// call print::print
// pop zero
//
// usage for reset:
// call print::reset
dw display: 0x20000
dw current: 0x20000
// prints the given text to the screen.
print:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // get string address argument
ldw current, rg1 // get current display position
print_loop:
ldb rg0, acc
stb acc, rg1
iadd rg0, 1
iadd rg1, 1
cmp acc, zero
jne print_loop
jmp end
// return
end:
stw rg1, current
mov bpr, spr
pop bpr
return
// resets the cursor position on the screen
reset:
push bpr
mov spr, bpr
ldw display, rg1
stw rg1, current
mov bpr, spr
pop bpr
return
Example Program (main.dsa)
include print "./print.dsa"
dw stack: 0x10000
db string: "'To confuse your enemy, you must first confuse yourself' - Probably Sun Tzu."
init:
// set up a stack.
ldw stack, bpr
mov bpr, spr
start:
lwi string, rg1
// push string address argument
push rg1
// call print function
call print::print
// clean up stack
pop rg1
hlt