# 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
**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:** ```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]`
`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:** ```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]`
`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:** ```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
**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]`
`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 "" // // 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 "" // // 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 ```