diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7585238 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +book diff --git a/book.toml b/book.toml new file mode 100644 index 0000000..fb4c064 --- /dev/null +++ b/book.toml @@ -0,0 +1,5 @@ +[book] +authors = ["zxq5", "nullndvoid"] +language = "en" +src = "src" +title = "damn_simple_architecture" diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..e10b99d --- /dev/null +++ b/src/README.md @@ -0,0 +1 @@ +# Introduction diff --git a/src/SUMMARY.md b/src/SUMMARY.md new file mode 100644 index 0000000..6aa4e34 --- /dev/null +++ b/src/SUMMARY.md @@ -0,0 +1,6 @@ +# Summary + +[Introduction](README.md) + +- [DSA](dsa/overview.md) + - [Syntax](dsa/syntax.md) diff --git a/src/dsa/overview.md b/src/dsa/overview.md new file mode 100644 index 0000000..9bfa999 --- /dev/null +++ b/src/dsa/overview.md @@ -0,0 +1 @@ +# DSA diff --git a/src/dsa/syntax.md b/src/dsa/syntax.md new file mode 100644 index 0000000..84c4b67 --- /dev/null +++ b/src/dsa/syntax.md @@ -0,0 +1,431 @@ +# 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:** + +```dsa +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:** + +```dsa +; 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:** +```dsa +; 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:** +```dsa +; 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:** +```dsa +; 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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +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:** +```dsa +include print "print.dsa" +include fib "fib.dsa" +``` +## Library Examples + +### Multiplication Library (multiply.dsa) + +```dsa +// 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) + +```dsa +// 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) + +```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 +``` \ No newline at end of file