427 lines
14 KiB
Markdown
427 lines
14 KiB
Markdown
# 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 `include` statement
|
|
- The `call` pseudo-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<br/>**on-read/write: protection fault (unless in kernel mode)** |
|
|
| `mmr` | Privileged | Hardware memory map table address<br/>**on-read/write: protection fault (unless in kernel mode)** |
|
|
| `zero` | Read-only | Always contains zero<br/>**on-read: always returns zero**<br/>**on-write: value is voided** |
|
|
| `pcx` | Read-only | Program counter<br/>**on-write: protection fault** |
|
|
| `noreg` | Placeholder | Indicates absence of register argument<br/>**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:**
|
|
```asm
|
|
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]`<br>`label, dest_reg [, offset]` | Load byte from memory |
|
|
| **LDBS** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load byte with sign extension |
|
|
| **LDH** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load half-word (16-bit) |
|
|
| **LDHS** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load half-word with sign extension |
|
|
| **LDW** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load word (32-bit) |
|
|
|
|
**Examples:**
|
|
```asm
|
|
; 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:**
|
|
```asm
|
|
; 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]`<br>`src_reg, label [, offset]` | Store byte to memory |
|
|
| **STH** | `src_reg, base_reg [, offset]`<br>`src_reg, label [, offset]` | Store half-word to memory |
|
|
| **STW** | `src_reg, base_reg [, offset]`<br>`src_reg, label [, offset]` | Store word to memory |
|
|
|
|
**Examples:**
|
|
```asm
|
|
; 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:**
|
|
```asm
|
|
; 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<br/>**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:**
|
|
```asm
|
|
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]`<br>`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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
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:**
|
|
```asm
|
|
include print "print.dsa"
|
|
include fib "fib.dsa"
|
|
```
|
|
## Library Examples
|
|
|
|
### Multiplication Library (multiply.dsa)
|
|
|
|
```asm
|
|
// 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)
|
|
|
|
```asm
|
|
// 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)
|
|
|
|
```asm
|
|
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
|
|
``` |