summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--.vscode/settings.json3
-rw-r--r--aliases.txt1
-rw-r--r--assembler.md123
-rw-r--r--assembler.ts250
-rwxr-xr-xbuild-bootloader.sh7
-rwxr-xr-xbuild-disk.sh3
-rw-r--r--code.a9
-rw-r--r--code/.vscode/settings.json3
-rw-r--r--code/bootloader.a109
-rw-r--r--code/calc.a74
-rw-r--r--code/code-1.a6
-rw-r--r--code/disk.a7
-rw-r--r--code/glumbo-buff.a285
-rw-r--r--code/glumbo.a271
-rw-r--r--code/hi.a11
-rw-r--r--code/memman.a154
-rw-r--r--code/move-bootloader.a62
-rw-r--r--code/move-bootloader.c11
-rw-r--r--code/printer.a111
-rw-r--r--code/strlib.a128
-rw-r--r--code/sub1.a6
-rw-r--r--code/test_aliases.a3
-rw-r--r--code/test_clock.a53
-rw-r--r--code/test_strlib.a10
-rw-r--r--code/wozmon.a160
-rw-r--r--instructions.md437
-rw-r--r--instructions/add.ts8
-rw-r--r--instructions/and.ts8
-rw-r--r--instructions/clr.ts8
-rw-r--r--instructions/cmp.ts9
-rw-r--r--instructions/cmr.ts10
-rw-r--r--instructions/crp.ts10
-rw-r--r--instructions/crr.ts11
-rw-r--r--instructions/dbg.ts13
-rw-r--r--instructions/dec.ts9
-rw-r--r--instructions/decr.ts10
-rw-r--r--instructions/div.ts8
-rw-r--r--instructions/halt.ts9
-rw-r--r--instructions/inc.ts9
-rw-r--r--instructions/incr.ts10
-rw-r--r--instructions/jmp.ts8
-rw-r--r--instructions/jmr.ts9
-rw-r--r--instructions/jnz.ts9
-rw-r--r--instructions/jnzr.ts11
-rw-r--r--instructions/jz.ts9
-rw-r--r--instructions/ld.ts9
-rw-r--r--instructions/ldm.ts8
-rw-r--r--instructions/ldr.ts8
-rw-r--r--instructions/mod.ts8
-rw-r--r--instructions/mul.ts8
-rw-r--r--instructions/not.ts8
-rw-r--r--instructions/or.ts8
-rw-r--r--instructions/put.ts9
-rw-r--r--instructions/ret.ts10
-rw-r--r--instructions/sbc.ts10
-rw-r--r--instructions/shl.ts9
-rw-r--r--instructions/shr.ts9
-rw-r--r--instructions/srm.ts8
-rw-r--r--instructions/srr.ts10
-rw-r--r--instructions/str.ts9
-rw-r--r--instructions/sub.ts8
-rw-r--r--instructions/swp.ts13
-rw-r--r--instructions/swpm.ts13
-rw-r--r--instructions/sys.ts55
-rw-r--r--instructions/xor.ts8
-rw-r--r--instructions_new/add.ts12
-rw-r--r--instructions_new/and.ts11
-rw-r--r--instructions_new/cmp.ts10
-rw-r--r--instructions_new/cmr.ts11
-rw-r--r--instructions_new/div.ts12
-rw-r--r--instructions_new/halt.ts9
-rw-r--r--instructions_new/jmp.ts9
-rw-r--r--instructions_new/jmr.ts10
-rw-r--r--instructions_new/jnz.ts10
-rw-r--r--instructions_new/jz.ts10
-rw-r--r--instructions_new/ld.ts11
-rw-r--r--instructions_new/mod.ts12
-rw-r--r--instructions_new/mov.ts9
-rw-r--r--instructions_new/mul.ts12
-rw-r--r--instructions_new/not.ts11
-rw-r--r--instructions_new/or.ts12
-rw-r--r--instructions_new/pop.ts12
-rw-r--r--instructions_new/push.ts12
-rw-r--r--instructions_new/ret.ts10
-rw-r--r--instructions_new/shl.ts11
-rw-r--r--instructions_new/shr.ts11
-rw-r--r--instructions_new/str.ts10
-rw-r--r--instructions_new/sub.ts12
-rw-r--r--instructions_new/swp.ts15
-rw-r--r--instructions_new/sys.ts60
-rw-r--r--instructions_new/xor.ts12
-rw-r--r--lib.ts5
-rw-r--r--pc.ts68
-rw-r--r--ramgen.ts116
-rw-r--r--readme.md19
-rw-r--r--redme.txt5
-rw-r--r--runtime.ts55
-rw-r--r--runtime_new.ts134
-rw-r--r--shit-instruction-set-262
-rw-r--r--test.ts3
-rw-r--r--the_e_programming_language/ast.json79
-rw-r--r--the_e_programming_language/ast.ts357
-rw-r--r--the_e_programming_language/code.txt11
-rw-r--r--the_e_programming_language/compiler.ts151
-rwxr-xr-xthe_e_programming_language/lang.ts31
-rwxr-xr-xthe_e_programming_language/test-2.e6
-rwxr-xr-xthe_e_programming_language/test.e43
-rwxr-xr-xthe_e_programming_language/test.e.txt43
-rwxr-xr-xthe_e_programming_language/tokenizer.ts171
110 files changed, 4408 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e9ab7f3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# the assembled text code
+*.p
+ram.bin
+iram.bin
+.vscode/6502-project.json
+code.o
+*.bin
+*.img
+thefile
+riscv
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b943dbc
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "deno.enable": true
+}
\ No newline at end of file
diff --git a/aliases.txt b/aliases.txt
new file mode 100644
index 0000000..9eda816
--- /dev/null
+++ b/aliases.txt
@@ -0,0 +1 @@
+jsr=jmr
\ No newline at end of file
diff --git a/assembler.md b/assembler.md
new file mode 100644
index 0000000..ee7abcc
--- /dev/null
+++ b/assembler.md
@@ -0,0 +1,123 @@
+# basic syntax
+
+unlike 99.9% of assembly languages, in this one, arguments are separated by spaces (no comma), also indentation doesn't matter, neither do labels, the cpu starts executing from top to bottom, code also doesn't have to be in a label for it to be executed
+
+example:
+
+```asm
+start:
+    mov a 1   ; put 1 into the a register
+    mov b 2   ; put 2 into the b register
+    add       ; add registers a and b and put it in c
+    str c 0   ; store c at address 0
+
+    ld a 0    ; load address 0 into a
+    mov b 14  ; put 14 into the b register
+    mul
+```
+
+# list of cool features that come with the assembler
+
+## code labels
+
+code labels add a way for you to make jumps without constantly changing the destinations because they're tied to line numbers
+
+example:
+```asm
+start:
+    mov a 1 ; change the 1 to a 0 to change result
+    cmp a 0
+    jnz zero
+    jmp one ; else, jump to one
+
+    zero:
+        halt ; if zero, halt
+    
+    one:
+        jmp one ; if one, infinite loop
+```
+
+## macros
+
+macros allow you to shorten how you do basic tasks (such as storing data in memory)
+
+example:
+```asm
+.macro store(val, addr) \
+    put a @val\
+    str a @addr
+
+store 1 0
+store 2 1
+store 2763 2
+```
+
+## labels
+
+basically a mix of a macro and a code label
+
+example:
+```asm
+.label one 1 ; one
+
+mov a one ; one -> reg A
+str a 0 ; reg A -> 0x0
+```
+
+## using code
+
+`#using` allows you to include code from other files
+
+example:
+```asm
+start:
+    mov a -1 ; 65535
+    str a 16 ; put our number into 16
+    #using printer.a
+    jmr print_num ; print number at 16 (well not print but stringify)
+    mov a 1 ; syscall 1 - write
+    mov b 1 ; fd 1 - stdout
+    mov c 32 ; from address 32
+    sys ; syscall
+```
+this will use printing code from `printer.a` to print the number 65535
+
+## data
+
+to insert data in your code (for example: a string) you can use the `.str` or `.hex` instruction(?) thingies
+
+dunno how to call them, anyways, example
+
+```asm
+mov a 1 ; write
+mov b 1 ; stdout
+mov c [string]
+sys
+end
+
+string:
+.str "is your refrigerator running?"
+```
+
+oh and btw, if you're using a label to keep track of their location (actually, what else would you use), reference them by doing `[NAME]` instead of `NAME` because due to some jank with how the emulator/assembler/whatever works i needed to offset the location for `NAME` references for jump instructions to work
+
+here's an example of using them as variable storage
+
+```asm
+init:
+    mov a 1
+    str a [counter]
+
+increment:
+    ld a [counter]
+    mov b 1
+    add
+    str c [counter]
+
+counter:
+.hex 0
+```
+
+##
+
+also i think raw code doesnt support indentation
\ No newline at end of file
diff --git a/assembler.ts b/assembler.ts
new file mode 100644
index 0000000..4ac2a93
--- /dev/null
+++ b/assembler.ts
@@ -0,0 +1,250 @@
+import dedent from "npm:dedent";
+import { PC } from "./pc.ts";
+const pc = new PC()
+const labels: Record<string, string> = {}
+
+const code = new TextDecoder()
+    .decode(Deno.readFileSync(Deno.args[0] ?? 'code.a'))
+
+const aliases = Object.fromEntries(new TextDecoder()
+    .decode(Deno.readFileSync('aliases.txt')).split('\n').map(a=>a.split('=')))
+
+const macros: Record<string, (args: string[]) => string> = {}
+
+interface DataAddr {
+    line: number,
+    offset: number
+}
+
+interface ObjectFile {
+    // number is the ammount of bytes to skip
+    code: (string | number)[],
+    offset: number,
+    // line number, data
+    data: [number, number[]][]
+}
+
+const object: ObjectFile = {
+    code: [],
+    data: [],
+    offset: 2**16 / 2
+}
+
+const advAliases: Record<string, string> = {
+    'mov,reg,addr': dedent`\
+        mov d @1
+        ld @0 d`,
+    'mov,addr,reg': dedent`\
+        mov d @0
+        str d @1`,
+    'str,reg,addr': dedent`\
+        mov d @1
+        str d @0`,
+    'ld,reg,addr':  dedent`\
+        mov d @1
+        ld @0 d`,
+    'add,': `add c a b`,
+    'sub,': `sub c a b`,
+    'mul,': `mul c a b`,
+    'div,': `div c a b`,
+}
+
+function processCode(rcode: string, offset: number = 0): (string | number)[] {
+    const code: (string | number)[] = rcode
+        .split('\n')
+        .map(l => l.trim())
+        .map(l => l.replace(/\s*(?<!(?<!\"[^"]*)\"[^"]*);.*$/gm, ''))
+        .map(l => l.replace(/(?<!(?<!\"[^"]*)\"[^"]*)'(.)'/g, (_, char) => char.charCodeAt(0).toString()))
+        .map(l => l.replace(/0x([0-9A-Fa-f]+)/g, (_, hex: string) => ''+parseInt(hex, 16)))
+        .filter(l => l)
+        .reduce((acc, l) => {
+            if (acc[acc.length - 1] && acc[acc.length - 1].endsWith('\\')) {
+                acc[acc.length - 1] = acc[acc.length - 1].slice(0, -1) + '\n'
+                acc[acc.length - 1] += l
+                return acc
+            }
+            acc.push(l)
+            return acc
+        }, [] as string[]);
+    const result: (string | number)[] = []
+
+    let i = offset;
+    let li = 0;
+    //parse macros
+    while (li < code.length) {
+        const el = code[li];
+        if (typeof el == 'number') {
+            li++;
+            continue;
+        }
+        const sel = el.split(' ');
+        li++;
+        if (sel[0] == '.macro') {
+            sel.shift();
+            let tx = sel.join(' ');
+            const pattern = /([A-z\-_0-9]+)\((.*?)\)\s*/g
+            const match = [...tx.matchAll(pattern)][0]
+            tx = tx.replace(pattern, '').replaceAll('\\n', '\n');
+            if (!match) throw 'knives at you'
+            const args = (match[2] ?? '').split(/,\s*/g)
+            macros[match[1]] = (args_: string[]) => {
+                let s = tx;
+                let i = 0
+                for (const a of args_) {
+                    s = s.replaceAll('@'+args[i], a)
+                    i++
+                }
+                return s
+            }
+            continue;
+        }
+        i++
+    }
+
+    // parse other
+    i = offset;
+    li = 0;
+    while (li < code.length) {
+        const el = code[li];
+        if (typeof el == 'number') {
+            li++;
+            continue;
+        }
+        const sel = el.split(' ');
+        li++;
+        if (el.endsWith(":")) {
+            console.log(sel[0], i)
+            labels[sel[0].replace(/:$/g,'')] = '$'+i;
+            labels[`[${sel[0].replace(/:$/g,'')}]`] = `[${i}]`;
+            continue;
+        }
+        if (sel[0] == '.label') {
+            labels[sel[1]] = sel[2];
+            continue;
+        }
+        if (macros[sel[0]]) {
+            const macro = macros[sel[0]]
+            sel.shift()
+            const r = macro(sel).split('\n')
+            i+=r.length
+            continue;
+        }
+        if (sel[0] == '.macro') {
+            continue;
+        }
+        if (sel[0] == '.offset') {
+            continue;
+        }
+        if (sel[0] == '#using') {
+            const newCode = processCode(new TextDecoder().decode(Deno.readFileSync(sel[1])), i + 1)
+            i += newCode.length + 1
+            continue;
+        }
+        i++
+    }
+
+    i = offset;
+    li = 0;
+    while (li < code.length) {
+        let el = code[li];
+        if (typeof el == 'number') {
+            result.push(el);
+            li++;
+            continue;
+        }
+        let sel = el.split(' ');
+        if (aliases[sel[0]]) el = el.replace(sel[0], aliases[sel[0]]);
+        li++;
+        if (macros[sel[0]]) {
+            for (const label of Object.keys(labels).sort((a, b) => b.length - a.length)) {
+                el = el.split(' ').map(a => a == label ? labels[label] : a).join(' ')
+            }
+            sel = el.split(' ')
+            const macro = macros[sel[0]]
+            sel.shift()
+            let rr = macro(sel)
+            for (const label of Object.keys(labels).sort((a, b) => b.length - a.length)) {
+                rr = rr.replace(label, labels[label])
+            }
+            const r = rr.split('\n')
+            result.push(...r)
+            i+=r.length
+            continue;
+        }
+        if (el.endsWith(":")) {
+            continue;
+        }
+        if (sel[0] == '.label') {
+            continue;
+        }
+        if (sel[0] == '.macro') {
+            continue;
+        }
+        if (sel[0] == '.offset') {
+            object.offset = +sel[1]
+            continue;
+        }
+        if (sel[0] == '#using') {
+            const newCode = processCode(new TextDecoder().decode(Deno.readFileSync(sel[1])), i + 1)
+            result.push(`jmp $${i+newCode.length+1}`) // skip over included code
+            result.push(...newCode)
+            i += newCode.length + 1
+            continue;
+        }
+        if (sel[0] == '.hex') {
+            object.data.push([
+                i,
+                [parseInt(sel[1], 16)]
+            ])
+            result.push(1)
+            i++;
+            continue;
+        }
+        if (sel[0] == '.str') {
+            const str = [...el.matchAll(/"(.*?)(?<!\\)"/g)][0][1].replaceAll('\\"', '"')
+            object.data.push([
+                i,
+                new Array(str.length).fill(0).map((_, i) => str.charCodeAt(i))
+            ])
+            result.push(str.length)
+            i++;
+            continue;
+        }
+        for (const label of Object.keys(labels).sort((a, b) => b.length - a.length)) {
+            el = el.split(' ').map(a => a == label ? labels[label] : a).join(' ')
+        }
+        const [cmd, ...args] = el.split(' ');
+        const argtypes = args.map((a: string) => {
+            if (pc.regNames.split('').includes(a)) return 'reg';
+            if (a.match(/^\$[0-9A-Fa-f]+$/g)) return 'addr';
+            return 'val';
+        })
+        if (advAliases[`${cmd},${argtypes.join(',')}`]) {
+            el = advAliases[`${cmd},${argtypes.join(',')}`].replace(/@([0-9]+)/g, (_m, arg) => {
+                if (argtypes[+arg] == 'addr') {
+                    return args[+arg].replace('$', '')
+                }
+                return args[+arg]
+            })
+            result.push(...el.split('\n'));
+            i += el.split('\n').length;
+            continue;
+        }
+        result.push(el.replace(/\$[0-9A-Fa-f]+/g, (_, addr) => addr))
+        i++
+    }
+    return result
+}
+
+object.code = processCode(code+'\nend')
+
+// console.log(labels)
+
+// for (const label of Object.keys(labels)) {
+//     result.push(`ld a ${labels[label]}`);
+//     result.push(`mov b ${labels[label]}`);
+//     result.push(`mov c 0`);
+//     result.push(`dbg ${label}`)
+// }
+
+Deno.writeTextFileSync('code.o', JSON.stringify(object))
diff --git a/build-bootloader.sh b/build-bootloader.sh
new file mode 100755
index 0000000..2bdb6bf
--- /dev/null
+++ b/build-bootloader.sh
@@ -0,0 +1,7 @@
+deno -A assembler.ts code/bootloader.a
+deno -A ramgen.ts
+cat iram.bin > diskloader.bin
+deno -A assembler.ts code/move-bootloader.a
+deno -A ramgen.ts
+cat iram.bin > bootloader.bin
+cat diskloader.bin >> iram.bin
\ No newline at end of file
diff --git a/build-disk.sh b/build-disk.sh
new file mode 100755
index 0000000..f09f086
--- /dev/null
+++ b/build-disk.sh
@@ -0,0 +1,3 @@
+deno -A assembler.ts $1
+deno -A ramgen.ts disk.img
+truncate -s 1440K thefile
\ No newline at end of file
diff --git a/code.a b/code.a
new file mode 100644
index 0000000..abb6021
--- /dev/null
+++ b/code.a
@@ -0,0 +1,9 @@
+start:
+    mov a -1 ; 65535
+    str a 16 ; put our number into 16
+    #using printer.a
+    jmr print_num ; print number at 16 (well not print but stringify)
+    mov a 1 ; write
+    mov b 1 ; stdout
+    mov c 32 ; address
+    sys ; syscall
\ No newline at end of file
diff --git a/code/.vscode/settings.json b/code/.vscode/settings.json
new file mode 100644
index 0000000..b943dbc
--- /dev/null
+++ b/code/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "deno.enable": true
+}
\ No newline at end of file
diff --git a/code/bootloader.a b/code/bootloader.a
new file mode 100644
index 0000000..66a221c
--- /dev/null
+++ b/code/bootloader.a
@@ -0,0 +1,109 @@
+.offset 0x6000 ; bootloader is in 0x6000, copied there by another script
+start:
+    mov a 0
+    str a [gottenNZ]
+    ; currSector -> A
+    mov a [currSector]
+    ld a a
+    str a 0x7cff
+
+    mov b 512
+    mul
+    str c [sectorOffset]
+
+    mov a 0
+    str a [bytePointer]
+
+    mov a 0
+    str a [ptrThing]
+
+    copySector:
+        mov a [sectorOffset]
+        ld a a
+        mov b [bytePointer]
+        ld b b
+        add c a b
+        ;
+        swp a c
+        mov b 0x8000 ; default code position
+        add c a b
+        str c [targetPointer]
+
+        ; ld a [sectorOffset]
+        mov a 0x7d00
+        ; add
+        ; swp c a
+        mov b [ptrThing]
+        ld b b
+        add c a b
+        mov b [targetPointer]
+        ld b b
+        ; swp c b
+        ; a <- $b
+        ld a b
+        push a ; push b
+        ld a c
+        ; push c ; push c
+        str b a ; $b <- c
+        pop a
+        ; $c <- b
+        str c a
+        ; swpm c b
+
+        ld a c
+        mov b 0
+        cmr a a b
+        mov b 1
+        xor c a b
+        swp a c
+        mov b [gottenNZ]
+        ld b b
+        or c a b
+        mov a [gottenNZ]
+        str c a
+
+        ;continue loop
+        ; pointer to 8xxx
+        mov a [ptrThing]
+        ld a a
+        mov b 1
+        add c a b
+        mov a [ptrThing]
+        str c a
+
+        ; pointer offset for sector thing
+        mov a [bytePointer]
+        ld a a
+        mov b 1
+        add
+        str c [bytePointer]
+
+        ; offset == 513
+        cmp c 513
+        jz copySector
+    ; continue main loop
+    mov a [currSector]
+    ld a a
+    mov b 1
+    add c a b
+    mov a [currSector]
+    str c a
+    mov a [gottenNZ]
+    ld a a
+    cmp a 0
+    jz start
+    ;escaped
+    jmp 0x8001
+
+ptrThing:
+.hex 0
+currSector:
+.hex 0
+sectorOffset:
+.hex 0
+bytePointer:
+.hex 0
+gottenNZ:
+.hex 0
+targetPointer:
+.hex 0
\ No newline at end of file
diff --git a/code/calc.a b/code/calc.a
new file mode 100644
index 0000000..2aa1b02
--- /dev/null
+++ b/code/calc.a
@@ -0,0 +1,74 @@
+.label len 1
+
+jmp start
+read_input:
+    mov a 0
+    mov b 0
+    mov c 64
+    sys
+    mov b 1
+    sub
+    str c len
+    ret
+
+str_to_num:
+    ; pointer to current character
+    .label ptr 2
+    ld a len
+    mov b 63
+    add
+    str c ptr
+    .label mult 3
+    mov a 1
+    str a mult
+    .label num 4
+    mov a 0
+    str a num
+    .label zero 48
+    stm_loop:
+        ;load char, subtract zero, multiply by 10
+        ld b ptr
+        ldr a b
+        mov b zero
+        sub
+        swp c a
+        ld b mult
+        mul
+
+        ; add to num
+        swp c b
+        ld a num
+        add
+        str c num
+
+        ld a mult
+        mov b 10
+        mul
+        str c mult
+
+        ; move pointer
+        ld a ptr
+        mov b 1
+        sub
+        str c ptr
+        cmp c 63
+        jz stm_loop
+    ret
+
+start:
+    jmr read_input
+    jmr str_to_num
+    ld a 4
+    str a 8 ; store number 1 to 8
+    jmr read_input
+    jmr str_to_num
+    ld a 4 ; load number from read
+    ld b 8
+    add
+    str c 16 ; put our number into 16
+    #using printer.a
+    jmr print_num ; print number at 16 (well not print but stringify)
+    mov a 1 ; write
+    mov b 1 ; stdout
+    mov c 32 ; address
+    sys ; syscall
\ No newline at end of file
diff --git a/code/code-1.a b/code/code-1.a
new file mode 100644
index 0000000..02be1b2
--- /dev/null
+++ b/code/code-1.a
@@ -0,0 +1,6 @@
+start:
+    mov a 42
+    str a 0
+    #using sub1.a
+    jmr do_the_thing
+    ld a 0
\ No newline at end of file
diff --git a/code/disk.a b/code/disk.a
new file mode 100644
index 0000000..35eb106
--- /dev/null
+++ b/code/disk.a
@@ -0,0 +1,7 @@
+start:
+    ; get sector 0
+    mov a 0
+    str a 0x7cff
+
+    ; jump to the sector
+    jmp 0x7d01
\ No newline at end of file
diff --git a/code/glumbo-buff.a b/code/glumbo-buff.a
new file mode 100644
index 0000000..8964ef3
--- /dev/null
+++ b/code/glumbo-buff.a
@@ -0,0 +1,285 @@
+; GLUMBO - the 2d game thing
+
+.macro store(reg, val, addr) \
+    put @reg @val\
+    str @reg @addr
+.macro storer(reg, val, addr) \
+    put @reg @val\
+    srr @reg @addr
+.macro inc(addr) \
+    ld a @addr\
+    put b 1\
+    add\
+    str c @addr
+
+jmp start
+get_coord:
+    ld a tmp2              ; Y(0-4) -> a
+    mov b width            ; width (5) -> b
+    mul                    ; Y(0-4) * width (5)
+
+    mov a grid_start       ; grid start address -> a
+    swp c b                ; (offset from y) -> b
+    add                    ; offsetY + gridStart
+    swp c a                ; -> a
+    ld b tmp1              ; X(0-4) -> b
+    add                    ; loc + X
+
+    str c tmp3             ; location -> tmp3
+    ret
+
+start:
+    .label width 20
+    .label height 10
+
+    .label grid_start 512
+    ; temp vars
+    .label tmp1 0
+    .label tmp2 1
+    .label tmp3 2
+    .label tmp4 3
+    .label tmp5 4
+
+    .label px 16
+    .label py 17
+    .label inp 128
+    .label rowBuff 256
+    store a 2 px
+    store a 2 py
+
+    store a 0 tmp1 ; x
+    store a 0 tmp2 ; y
+    mov a 2
+    mov b 1
+    sys
+    grid_loop:
+        ;get coord
+            jmr get_coord
+        ;store tile
+            ; storer a 46 c
+        ;main loop stuff
+        ; place tile
+            ; get X % (width - 1) to check if on x edge
+                store a 46 tmp4
+                mov a width         ; width -> A
+                mov b 1             ; 1 -> b
+                sub                 ; c = width - 1
+                swp c b             ; -> b
+                ld a tmp1           ; x -> a
+                mod                 ; c = x % (w - 1)
+                mov a 0             ;
+                crr c c a           ; c = c == 0?
+                str c tmp5          ; c -> tmp5
+
+            ; Y % (height - 1 )
+                mov a height        ; height -> A
+                mov b 1             ; 1 -> b
+                sub                 ; c = height - 1
+                swp c b             ; -> b
+                ld a tmp2           ; x -> a
+                mod                 ; c = x % (w - 1)
+                mov a 0
+                crr a c a           ; a = c == 0?
+
+            ld b tmp5
+            or
+            cmp c 1
+
+            jz do_the_store     ; edge ? continue : jmp do_the_store
+            store a 35 tmp4     ; store 35 at tmp4
+            do_the_store:
+                ld b tmp3       ; location -> b
+                ld a tmp4       ; tmp4 (character) -> a
+                srr a b         ; store the tile
+        ;;;;;;;;;;;;;;;;;;;;;;;;;
+        mov a width             ; width -> a
+        mov b 1                 ; 1 -> b
+        sub                     ; c = width - 1
+        ld a tmp1               ; X(0-4) -> a
+        cmr a c                 ; X(0-4) == width
+        jnz ifz                 ; go to ifz if X(0-4) == width (5)
+        ifnz:                   ; X is not 0
+            ld a tmp1           ; X -> a
+            mov b 1             ; 1 -> b
+            add                 ; X + 1
+            str c tmp1          ; X = X + 1
+            jmp continue_loop   ; continue
+        ifz:                    ; X is 0
+            store a 0 tmp1      ; set X to 1
+            ld a tmp2           ; Y(0-4) -> a
+            mov b 1             ; 1 -> b
+            add                 ; c = Y + 1
+            str c tmp2          ; Y = c
+            jmp continue_loop   ; continue
+        continue_loop:
+            mov a height
+            mov b 0
+            sub
+            ld a tmp2           ; get Y (0-4)
+            cmr a c             ; Y == height+1 ?
+            jz grid_loop        ; if not, continue
+    ; escaped
+    main_loop:
+        jmr print
+        ; get input
+            mov a 0
+            mov b 0
+            mov c inp
+            sys
+            jmr parse_input
+        jmp main_loop
+
+parse_input:
+    .macro case(addr, val, ln) \
+        ld a @addr\
+        cmp a @val\
+        jnz @ln
+    .macro break() jmp default
+
+    case inp 119 case_w
+    case inp 115 case_s
+    case inp 97 case_a
+    case inp 100 case_d
+
+    case inp 99 case_c
+    case inp 3 case_c
+    break
+
+    case_w:
+        ld a py
+        cmp a 0
+        jnz default
+        mov b 1
+        sub
+        str c py
+        break
+    
+    case_s:
+        ; width-1
+            mov a height
+            mov b 1
+            sub
+
+        ld a py
+        cmr a c
+        jnz default
+        mov b 1
+        add
+        str c py
+        break
+    
+    case_a:
+        ld a px
+        cmp a 0
+        jnz default
+        mov b 1
+        sub
+        str c px
+        break
+    
+    case_d:
+        ; width-1
+            mov a width
+            mov b 1
+            sub
+
+        ld a px
+        cmr a c
+        jnz default
+        mov b 1
+        add
+        str c px
+        break
+    
+    case_c:
+        end
+        break
+
+    default:
+        ret
+
+print:
+    .label tmp6 5
+    mov a 1
+    mov b 1
+    mov c [clear]
+    sys
+    store a 0 tmp1 ; x
+    store a 0 tmp2 ; y
+    store a 0 tmp6 ; rowBuff index
+    print_loop:
+        ;get coord
+            jmr get_coord
+        ; get tile
+            ld a tmp1 ; x
+            ld b px   ; player x
+            crr c a b
+            str c tmp4
+            ld a tmp2 ; y
+            ld b py   ; player y
+            crr b a b
+            ld a tmp4
+            and
+            cmp c 1
+            
+            ld a tmp6 ; buff pointer
+            mov b rowBuff ; + buff loc
+            add ;
+            ld a tmp3 ; tile pointer?
+            ldr b a ; load tile into b
+
+            jz set_normal
+                mov b 64
+            set_normal:
+            srr b c ; store b to c
+            ; store a 0 129
+        ;loop
+            mov a width
+            mov b 1
+            sub
+            ld a tmp1              ; X(0-4) -> a
+            cmr a c                ; X(0-4) == width
+            jnz p_ifz              ; go to ifz if X(0-4) == width
+            p_ifnz:                ; X is not 0
+                ld a tmp1          ; X -> a
+                mov b 1            ; 1 -> b
+                add                ; X + 1
+                str c tmp1         ; X = X + 1
+                inc tmp6
+                jmp continue_ploop ; continue
+            p_ifz:                 ; X is 0
+                store a 0 tmp6
+                store a 10 128
+                store a 0 129
+                mov a 1
+                mov b 1
+                mov c 128
+                sys
+                store a 0 tmp1     ; set X to 1
+                ld a tmp2          ; Y(0-4) -> a
+                mov b 1            ; 1 -> b
+                add                ; c = Y + 1
+                str c tmp2         ; Y = c
+                ; print
+                    ; print
+                    mov a 1
+                    mov b 1
+                    mov c rowBuff
+                    sys
+                    ; ld c 128
+                    ; dbg a
+                jmp continue_ploop ; continue
+            continue_ploop:
+                mov a height
+                mov b 0
+                sub
+                ld a tmp2          ; get Y (0-4)
+                cmr a c            ; Y == width+1 ?
+                jz print_loop      ; if not, continue
+    ret
+clear:
+.hex 1b
+.str "[2J"
+.hex 1b
+.str "[0;0H"
+.hex 0
\ No newline at end of file
diff --git a/code/glumbo.a b/code/glumbo.a
new file mode 100644
index 0000000..72accf6
--- /dev/null
+++ b/code/glumbo.a
@@ -0,0 +1,271 @@
+; GLUMBO - the 2d game thing
+
+.macro store(reg, val, addr) \
+    put @reg @val\
+    str @reg @addr
+.macro storer(reg, val, addr) \
+    put @reg @val\
+    srr @reg @addr
+
+jmp start
+get_coord:
+    ld a tmp2              ; Y(0-4) -> a
+    mov b width            ; width (5) -> b
+    mul                    ; Y(0-4) * width (5)
+
+    mov a grid_start       ; grid start address -> a
+    swp c b                ; (offset from y) -> b
+    add                    ; offsetY + gridStart
+    swp c a                ; -> a
+    ld b tmp1              ; X(0-4) -> b
+    add                    ; loc + X
+
+    str c tmp3             ; location -> tmp3
+    ret
+
+start:
+    .label width 20
+    .label height 10
+
+    .label grid_start 512
+    ; temp vars
+    .label tmp1 0
+    .label tmp2 1
+    .label tmp3 2
+    .label tmp4 3
+    .label tmp5 4
+
+    .label px 16
+    .label py 17
+    .label inp 256
+    store a 2 px
+    store a 2 py
+
+    store a 0 tmp1 ; x
+    store a 0 tmp2 ; y
+    mov a 2
+    mov b 1
+    sys
+    grid_loop:
+        ;get coord
+            jmr get_coord
+        ;store tile
+            ; storer a 46 c
+        ;main loop stuff
+        ; place tile
+            ; get X % (width - 1) to check if on x edge
+                store a 46 tmp4
+                mov a width         ; width -> A
+                mov b 1             ; 1 -> b
+                sub                 ; c = width - 1
+                swp c b             ; -> b
+                ld a tmp1           ; x -> a
+                mod                 ; c = x % (w - 1)
+                mov a 0             ;
+                crr c c a           ; c = c == 0?
+                str c tmp5          ; c -> tmp5
+
+            ; Y % (height - 1 )
+                mov a height        ; height -> A
+                mov b 1             ; 1 -> b
+                sub                 ; c = height - 1
+                swp c b             ; -> b
+                ld a tmp2           ; x -> a
+                mod                 ; c = x % (w - 1)
+                mov a 0
+                crr a c a           ; a = c == 0?
+
+            ld b tmp5
+            or
+            cmp c 1
+
+            jz do_the_store     ; edge ? continue : jmp do_the_store
+            store a 35 tmp4     ; store 35 at tmp4
+            do_the_store:
+                ld b tmp3       ; location -> b
+                ld a tmp4       ; tmp4 (character) -> a
+                srr a b         ; store the tile
+        ;;;;;;;;;;;;;;;;;;;;;;;;;
+        mov a width             ; width -> a
+        mov b 1                 ; 1 -> b
+        sub                     ; c = width - 1
+        ld a tmp1               ; X(0-4) -> a
+        cmr a c                 ; X(0-4) == width
+        jnz ifz                 ; go to ifz if X(0-4) == width (5)
+        ifnz:                   ; X is not 0
+            ld a tmp1           ; X -> a
+            mov b 1             ; 1 -> b
+            add                 ; X + 1
+            str c tmp1          ; X = X + 1
+            jmp continue_loop   ; continue
+        ifz:                    ; X is 0
+            store a 0 tmp1      ; set X to 1
+            ld a tmp2           ; Y(0-4) -> a
+            mov b 1             ; 1 -> b
+            add                 ; c = Y + 1
+            str c tmp2          ; Y = c
+            jmp continue_loop   ; continue
+        continue_loop:
+            mov a height
+            mov b 0
+            sub
+            ld a tmp2           ; get Y (0-4)
+            cmr a c             ; Y == height+1 ?
+            jz grid_loop        ; if not, continue
+    ; escaped
+    main_loop:
+        jmr print
+        ; get input
+            mov a 0
+            mov b 0
+            mov c inp
+            sys
+            jmr parse_input
+        jmp main_loop
+
+parse_input:
+    .macro case(addr, val, ln) \
+        ld a @addr\
+        cmp a @val\
+        jnz @ln
+    .macro break() jmp default
+
+    case inp 119 case_w
+    case inp 115 case_s
+    case inp 97 case_a
+    case inp 100 case_d
+
+    case inp 99 case_c
+    case inp 3 case_c
+    break
+
+    case_w:
+        ld a py
+        cmp a 0
+        jnz default
+        mov b 1
+        sub
+        str c py
+        break
+    
+    case_s:
+        ; width-1
+            mov a width
+            mov b 1
+            sub
+
+        ld a py
+        cmr a c
+        jnz default
+        mov b 1
+        add
+        str c py
+        break
+    
+    case_a:
+        ld a px
+        cmp a 0
+        jnz default
+        mov b 1
+        sub
+        str c px
+        break
+    
+    case_d:
+        ; width-1
+            mov a width
+            mov b 1
+            sub
+
+        ld a px
+        cmr a c
+        jnz default
+        mov b 1
+        add
+        str c px
+        break
+    
+    case_c:
+        halt
+        break
+
+    default:
+        ret
+
+print:
+    mov a 1
+    mov b 1
+    mov c [clear]
+    sys
+    store a 0 tmp1 ; x
+    store a 0 tmp2 ; y
+    print_loop:
+        ;get coord
+            jmr get_coord
+        ; get tile
+            ld a tmp3
+            ldr b a
+            str b 128
+            store a 0 129
+
+            ;TODO - make player tile be a @ or something
+            ld a tmp1 ; x
+            ld b px   ; player x
+            crr c a b
+            str c tmp4
+            ld a tmp2 ; y
+            ld b py   ; player y
+            crr b a b
+            ld a tmp4
+            and
+            cmp c 1
+            jz print_normal
+                store a 64 128
+            print_normal:
+                ; print
+                mov a 1
+                mov b 1
+                mov c 128
+                sys
+                ; ld c 128
+                ; dbg a
+        ;loop
+            mov a width
+            mov b 1
+            sub
+            ld a tmp1              ; X(0-4) -> a
+            cmr a c                ; X(0-4) == width
+            jnz p_ifz              ; go to ifz if X(0-4) == width
+            p_ifnz:                ; X is not 0
+                ld a tmp1          ; X -> a
+                mov b 1            ; 1 -> b
+                add                ; X + 1
+                str c tmp1         ; X = X + 1
+                jmp continue_ploop ; continue
+            p_ifz:                 ; X is 0
+                store a 10 128
+                store a 0 129
+                mov a 1
+                mov b 1
+                mov c 128
+                sys
+                store a 0 tmp1     ; set X to 1
+                ld a tmp2          ; Y(0-4) -> a
+                mov b 1            ; 1 -> b
+                add                ; c = Y + 1
+                str c tmp2         ; Y = c
+                jmp continue_ploop ; continue
+            continue_ploop:
+                mov a height
+                mov b 0
+                sub
+                ld a tmp2          ; get Y (0-4)
+                cmr a c            ; Y == width+1 ?
+                jz print_loop      ; if not, continue
+    ret
+clear:
+.hex 1b
+.str "[2J"
+.hex 1b
+.str "[0;0H"
+.hex 0
\ No newline at end of file
diff --git a/code/hi.a b/code/hi.a
new file mode 100644
index 0000000..62b1db8
--- /dev/null
+++ b/code/hi.a
@@ -0,0 +1,11 @@
+start:
+    mov a 1
+    mov b 1
+    mov c [helloworld]
+    sys
+    halt
+
+helloworld:
+.str "Hello, World!"
+.hex 0xA
+.hex 0
\ No newline at end of file
diff --git a/code/memman.a b/code/memman.a
new file mode 100644
index 0000000..2398cd6
--- /dev/null
+++ b/code/memman.a
@@ -0,0 +1,154 @@
+; MEMMAN - memory manager
+
+jmp start
+
+#using code/printer.a
+
+; code from calc.a
+; call with length in A
+str_to_num:
+    ; pointer to current character
+    ; ld a len
+    ld b [stm_start]
+    add
+    str c [ptr]
+    mov a 1
+    str a [mult]
+    mov a 0
+    str a [num]
+    .label zero 48
+    stm_loop:
+        ;load char, subtract zero, multiply by 10
+        ld b [ptr]
+        ldr a b
+        mov b zero
+        sub
+        swp c a
+        ld b [mult]
+        mul
+
+        ; add to num
+        swp c b
+        ld a [num]
+        add
+        str c [num]
+
+        ld a [mult]
+        mov b 10
+        mul
+        str c [mult]
+
+        ; move pointer
+        ld a [ptr]
+        mov b 1
+        sub
+        str c [ptr]
+        ld b [stm_start]
+        cmr c b
+        jz stm_loop
+    ret
+
+get_input:
+    mov a 0
+    mov b 0
+    mov c [input]
+    sys
+    str a [len]
+    ret
+
+parse_input:
+    mov a 0
+    str a [inp_ptr]
+
+    .macro case(addr, val, ln) \
+        ld a @addr\
+        cmp a @val\
+        jnz @ln
+    .macro break() jmp default
+
+    case [input] 'g' case_g
+    break
+
+    case_g:
+        ; get pointer to number
+            mov a [input]
+            mov b 1
+            add
+            str c [stm_start]
+        ; get new length
+            ld a [len]
+            mov b 2 ; subtract 2 for command + \n at the end
+            sub
+            swp c a 
+        jmr str_to_num
+        ld a [num]
+        dbg 3
+        str a 16
+        jmr print_num
+        ; print the output
+            mov a 1 ; write
+            mov b 1 ; stdout
+            mov c 32 ; address
+            sys ; syscall
+        mov a 1
+        mov b 1
+        mov c [colon_space]
+        sys
+        ldm a [num]
+        str a 16
+        jmr print_num
+        ; print the output
+            mov a 1 ; write
+            mov b 1 ; stdout
+            mov c 32 ; address
+            sys ; syscall
+        break
+
+    default:
+        ret
+
+
+start:
+    mov a 2
+    mov b 0
+    sys
+    jmr get_input
+    jmr parse_input
+    halt
+
+startup_message:
+.str "welcome to mem man the memory manager of the memory of managing the memory"
+.hex 0xa
+.str "yeah"
+.hex 0xa
+.hex 0xa
+.hex 0
+err:
+.str "what the fuck is this"
+.hex 0xa
+.hex 0
+ptr:
+.hex 0
+mult:
+.hex 0
+num:
+.hex 0
+; 256 bytes of input
+input:
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+.str "0000000000000000000000000000000000000000000000000000000000000000"
+len:
+.hex 0
+inp_ptr:
+.hex 0
+stm_start:
+.hex 0
+colon_space:
+.str ": "
+.hex 0
\ No newline at end of file
diff --git a/code/move-bootloader.a b/code/move-bootloader.a
new file mode 100644
index 0000000..306f2fe
--- /dev/null
+++ b/code/move-bootloader.a
@@ -0,0 +1,62 @@
+start:
+    ; init stack
+    mov a 0x6000
+    mov b 0x7000
+    str b a
+    copyLoop:
+        mov a [codePointer]
+        ld a a
+        mov b 0x6000
+        add c a b
+        mov a [targetPointer]
+        str c a
+
+        mov a codeStart
+        mov b [codePointer]
+        ld b b
+        add c a b
+        
+        mov a [targetPointer]
+        ld a a
+        ; swp a c
+        ; a <- $b
+        ld d c
+        push d ; push b
+        ld d a
+        ; push a ; push a
+        str c d ; $b <- a
+        pop d
+        ; $a <- b
+        str a d
+        ; swpm c b
+        
+        mov a [codePointer]
+        ld a a
+        mov b 1
+        add c a b
+        ; mov a
+        str c [codePointer] 
+        ; continue loop
+            mov b [targetPointer]
+            ; (byte we just copied) -> B
+            ld b b
+            ; (next byte) -> A
+            ld a c
+            ; C = A (aka next byte) == 0
+            cmr c a 0
+            ; A = B (aka last byte) == 1E (end instruction)
+            cmr a b 0x1e
+            swp c b ; C -> B
+            and c a b; c=a&&b
+            mov a 1
+            cmp c a ; c==1?
+            jz copyLoop ; continue if c != 1
+    jmp 0x6001
+
+
+targetPointer:
+.hex 0
+codePointer:
+.hex 0
+; start of bootloader
+codeStart:
\ No newline at end of file
diff --git a/code/move-bootloader.c b/code/move-bootloader.c
new file mode 100644
index 0000000..1aa938a
--- /dev/null
+++ b/code/move-bootloader.c
@@ -0,0 +1,11 @@
+#define codeStart 900
+
+int main() {
+    // set up stack
+    *(volatile unsigned char *)0x7000 = 0x6000;
+    volatile unsigned char* codePointer = 0;
+    while ()
+    {
+        volatile unsigned char* targetPointer = 0x6000 + codePointer;
+    }
+}
\ No newline at end of file
diff --git a/code/printer.a b/code/printer.a
new file mode 100644
index 0000000..87b66ba
--- /dev/null
+++ b/code/printer.a
@@ -0,0 +1,111 @@
+; print the number at 0xF
+print_num:
+    ; non-address definitions
+    .label zero 48
+    .label out_start 32
+    ; define stuff in memory
+    .label number 16
+    .label mult 17
+    mov a 1
+    str a mult
+    .label currnum 18
+    .label tmp1 19
+    .label out_pointer 20
+    mov a out_start
+    str a out_pointer
+    .label swap_counter 21
+
+    loop_start:
+        ; get num-(num%mult)
+            ld a number
+            ld b mult
+            mod
+            swp c b
+            sub
+            str c tmp1
+
+        ; get num-(num%(mult*10))
+            mov a 10
+            ld b mult
+            mul
+            swp c b
+            ld a number
+            mod
+            swp c b
+            sub
+        
+        ; subtract the thingies to get the current digit
+        swp c b
+        ld a tmp1
+        sub
+        swp c a
+        ld b mult
+        div
+        str c currnum
+
+        ; add zero to currnum and store at out_pointer
+        swp a c ; currnum -> A
+        mov b zero
+        add
+        ld a out_pointer
+        srr c a ; store c to address at a (which is out_pointer)
+
+        ; continue loop
+            ; increment out_pointer
+            ld a out_pointer
+            mov b 1
+            add
+            str c out_pointer
+            ; increment mult
+            ld a mult
+            mov b 10
+            mul
+            str c mult
+        
+            swp c b ; mult -> b
+            ld a number ; get number
+            mod ; get mod, will be equal to number if reached end
+            cmr c a ; compare result of mod and number (which is still in a)
+            jz loop_start ; jump if not equal
+    ; escaped from loop; swapping around memory to flip the text
+    ld a out_pointer
+    mov b out_start
+    sub
+    swp c a
+    mov b 2
+    div
+    str c swap_counter
+    cmp c 0
+    jnz end_swap
+    start_swap:
+        ; ptr - counter
+            ld b swap_counter
+            ld a out_pointer
+            sub
+            str c tmp1
+        ; start + counter
+            ld a swap_counter ; 1
+            mov b 1
+            sub ; 1
+            swp c b ; 1 -> b
+            mov a out_start ; 32
+            add ; 32 + 1 = 33
+        swp c b
+        ld a tmp1
+        swpm a b
+        ld a swap_counter
+        mov b 1
+        sub
+        str c swap_counter
+        cmp c 0
+        jz start_swap
+    end_swap:
+    ; add \n\0
+    ld b out_pointer
+    mov a 10 ; \n
+    srr a b
+    mov a 1
+    add
+    mov a 0 ; \0
+    srr a c
+    ret
diff --git a/code/strlib.a b/code/strlib.a
new file mode 100644
index 0000000..a18da3b
--- /dev/null
+++ b/code/strlib.a
@@ -0,0 +1,128 @@
+; number to string
+; a - pointer to output
+; b - number to print
+num_to_str:
+    str a out_pointer
+    str a out_start
+    str b [number]
+    ; non-address definitions
+    .label zero 48
+    ; define stuff in memory
+    ; .label number 16
+    ; .label mult 17
+    ; mov a 1
+    ; str a mult
+    ; .label currnum 18
+    ; .label tmp1 19
+    ; .label swap_counter 21
+
+    loop_start:
+        ; get num-(num%mult)
+            ld a [number]
+            ld b [mult]
+            mod
+            swp c b
+            sub
+            str c [tmp1]
+
+        ; get num-(num%(mult*10))
+            mov a 10
+            ld b [mult]
+            mul
+            swp c b
+            ld a [number]
+            mod
+            swp c b
+            sub
+        
+        ; subtract the thingies to get the current digit
+        swp c b
+        ld a [tmp1]
+        sub
+        swp c a
+        ld b [mult]
+        div
+        str c [currnum]
+
+        ; add zero to currnum and store at out_pointer
+        swp a c ; currnum -> A
+        mov b zero
+        add
+        ld a [out_pointer]
+        srr c a ; store c to address at a (which is out_pointer)
+
+        ; continue loop
+            ; increment out_pointer
+            ld a [out_pointer]
+            mov b 1
+            add
+            str c [out_pointer]
+            ; increment mult
+            ld a [mult]
+            mov b 10
+            mul
+            str c [mult]
+        
+            swp c b ; mult -> b
+            ld a [number] ; get number
+            mod ; get mod, will be equal to number if reached end
+            cmr c a ; compare result of mod and number (which is still in a)
+            jz loop_start ; jump if not equal
+    ; escaped from loop; swapping around memory to flip the text
+    ld a [out_pointer]
+    ld b [out_start]
+    sub
+    swp c a
+    mov b 2
+    div
+    str c [swap_counter]
+    cmp c 0
+    jnz end_swap
+    start_swap:
+        ; ptr - counter
+            ld b [swap_counter]
+            ld a [out_pointer]
+            sub
+            str c [tmp1]
+        ; start + counter
+            ld a [swap_counter] ; 1
+            mov b 1
+            sub ; 1
+            swp c b ; 1 -> b
+            ld a [out_start] ; 32
+            add ; 32 + 1 = 33
+        swp c b
+        ld a [tmp1]
+        dbg 304
+        swpm a b
+        ld a [swap_counter]
+        mov b 1
+        sub
+        str c [swap_counter]
+        cmp c 0
+        jz start_swap
+    end_swap:
+    ; add \n\0
+    ld b [out_pointer]
+    mov a 10 ; \n
+    srr a b
+    mov a 1
+    add
+    mov a 0 ; \0
+    srr a c
+    ret
+
+out_pointer:
+.hex 0
+out_start:
+.hex 0
+number:
+.hex 0
+mult:
+.hex 1
+currnum:
+.hex 0
+tmp1:
+.hex 0
+swap_counter:
+.hex 0
\ No newline at end of file
diff --git a/code/sub1.a b/code/sub1.a
new file mode 100644
index 0000000..e84f782
--- /dev/null
+++ b/code/sub1.a
@@ -0,0 +1,6 @@
+do_the_thing:
+    ld a 0
+    mov b 1
+    sub
+    str c 0
+    ret
\ No newline at end of file
diff --git a/code/test_aliases.a b/code/test_aliases.a
new file mode 100644
index 0000000..f63b4f5
--- /dev/null
+++ b/code/test_aliases.a
@@ -0,0 +1,3 @@
+start:
+    mov a 50
+    mov $0 a
\ No newline at end of file
diff --git a/code/test_clock.a b/code/test_clock.a
new file mode 100644
index 0000000..fe0f539
--- /dev/null
+++ b/code/test_clock.a
@@ -0,0 +1,53 @@
+.label counter 0
+
+jmp start
+
+interrupt:
+    ld a counter
+    mov b 1
+    add
+    swp c a
+    mov b 100
+    mod
+    str c counter
+    cmp c 0
+    jnz print_numb
+    ret
+
+#using code/printer.a
+
+print_numb:
+    ld a [counter]
+    mov b 1
+    add
+    str c [counter]
+    str c 16 ; put our number into 16
+    jmr print_num ; print number at 16 (well not print but stringify)
+    mov a 1 ; write
+    mov b 1 ; stdout
+    mov c 32 ; address
+    sys ; syscall
+    ret
+
+
+start:
+    mov a helloworld
+    mov b 1
+    sub
+    mov a 1
+    mov b 1
+    sys
+    mov a interrupt
+    mov b 1
+    sub
+    str c 0x7000
+    ; nl:
+    ; jmp nl
+    halt
+
+helloworld:
+.str "Hello, World!"
+.hex a
+.hex 0
+counter:
+.hex 0
\ No newline at end of file
diff --git a/code/test_strlib.a b/code/test_strlib.a
new file mode 100644
index 0000000..ce65675
--- /dev/null
+++ b/code/test_strlib.a
@@ -0,0 +1,10 @@
+#using code/strlib.a
+start:
+    mov a 16
+    mov b -1
+    jmr num_to_str
+    mov a 1
+    mov b 1
+    mov c 16
+    sys
+    end
\ No newline at end of file
diff --git a/code/wozmon.a b/code/wozmon.a
new file mode 100644
index 0000000..5462c4d
--- /dev/null
+++ b/code/wozmon.a
@@ -0,0 +1,160 @@
+;  The WOZ Monitor for the Apple 1
+;  Written by Steve Wozniak in 1976
+
+
+; Page 0 Variables
+
+.label XAML            0x24           ;  Last "opened" location Low
+.label XAMH            0x25           ;  Last "opened" location High
+.label STL             0x26           ;  Store address Low
+.label STH             0x27           ;  Store address High
+.label L               0x28           ;  Hex value parsing Low
+.label H               0x29           ;  Hex value parsing High
+.label YSAV            0x2A           ;  Used to see if hex value is given
+.label MODE            0x2B           ;  $00=XAM, $7F=STOR, $AE=BLOCK XAM
+
+
+; Other Variables
+
+.label IN              0x0200         ;  Input buffer to $027F
+.label KBD             0xD010         ;  PIA.A keyboard input
+.label KBDCR           0xD011         ;  PIA.A keyboard control register
+.label DSP             0xD012         ;  PIA.B display output register
+.label DSPCR           0xD013         ;  PIA.B display control register
+
+               .org $FF00
+               .export RESET
+
+RESET:          ;CLD             ; Clear decimal arithmetic mode.
+                ;CLI
+                MOV Y 0x7F        ; Mask for DSP data direction register.
+                STY DSP         ; Set it up.
+                MOV A 0xA7        ; KBD and DSP control register mask.
+                STA KBDCR       ; Enable interrupts, set CA1, CB1, for
+                STA DSPCR       ;  positive edge sense/output mode.
+NOTCR:          CMP #'_'+$80    ; "_"?
+                BEQ BACKSPACE   ; Yes.
+                CMP 0x9B        ; ESC?
+                BEQ ESCAPE      ; Yes.
+                INY             ; Advance text index.
+                BPL NEXTCHAR    ; Auto ESC if > 127.
+ESCAPE:         LD A #'\'+$80    ; "\".
+                JSR ECHO        ; Output it.
+GETLINE:        LD A 0x8D        ; CR.
+                JSR ECHO        ; Output it.
+                LD Y 0x01        ; Initialize text index.
+BACKSPACE:      DEY             ; Back up text index.
+                BMI GETLINE     ; Beyond start of line, reinitialize.
+NEXTCHAR:       LD A KBDCR       ; Key ready?
+                BPL NEXTCHAR    ; Loop until ready.
+                LD A KBD         ; Load character. B7 should be ‘1’.
+                STA IN,Y        ; Add to text buffer.
+                JSR ECHO        ; Display character.
+                CMP 0x8D        ; CR?
+                BNE NOTCR       ; No.
+                LD Y 0xFF        ; Reset text index.
+                LD A 0x00        ; For XAM mode.
+                TAX             ; 0->X.
+SETSTOR:        ASL             ; Leaves $7B if setting STOR mode.
+SETMODE:        STA MODE        ; $00=XAM, $7B=STOR, $AE=BLOCK XAM.
+BLSKIP:         INY             ; Advance text index.
+NEXTITEM:       LD A IN,Y        ; Get character.
+                CMP 0x8D        ; CR?
+                BEQ GETLINE     ; Yes, done this line.
+                CMP #'.'+$80    ; "."?
+                BCC BLSKIP      ; Skip delimiter.
+                BEQ SETMODE     ; Set BLOCK XAM mode.
+                CMP #':'+$80    ; ":"?
+                BEQ SETSTOR     ; Yes. Set STOR mode.
+                CMP #'R'+$80    ; "R"?
+                BEQ RUN         ; Yes. Run user program.
+                STX L           ; $00->L.
+                STX H           ;  and H.
+                STY YSAV        ; Save Y for comparison.
+NEXTHEX:        LD A IN,Y        ; Get character for hex test.
+                EOR 0xB0        ; Map digits to $0-9.
+                CMP 0x0A        ; Digit?
+                BCC DIG         ; Yes.
+                ADC 0x88        ; Map letter "A"-"F" to $FA-FF.
+                CMP 0xFA        ; Hex letter?
+                BCC NOTHEX      ; No, character not hex.
+DIG:            ASL
+                ASL             ; Hex digit to MSD of A.
+                ASL
+                ASL
+                LD X 0x04        ; Shift count.
+HEXSHIFT:       ASL             ; Hex digit left, MSB to carry.
+                ROL L           ; Rotate into LSD.
+                ROL H           ; Rotate into MSD’s.
+                DEX             ; Done 4 shifts?
+                BNE HEXSHIFT    ; No, loop.
+                INY             ; Advance text index.
+                BNE NEXTHEX     ; Always taken. Check next character for hex.
+NOTHEX:         CPY YSAV        ; Check if L, H empty (no hex digits).
+                BEQ ESCAPE      ; Yes, generate ESC sequence.
+                BIT MODE        ; Test MODE byte.
+                BVC NOTSTOR     ; B6=0 STOR, 1 for XAM and BLOCK XAM
+                LD A L           ; LSD’s of hex data.
+                STA (STL,X)     ; Store at current ‘store index’.
+                INC STL         ; Increment store index.
+                BNE NEXTITEM    ; Get next item. (no carry).
+                INC STH         ; Add carry to ‘store index’ high order.
+TONEXTITEM:     JMP NEXTITEM    ; Get next command item.
+RUN:            JMP (XAML)      ; Run at current XAM index.
+NOTSTOR:        BMI XAMNEXT     ; B7=0 for XAM, 1 for BLOCK XAM.
+                LD X 0x02        ; Byte count.
+SETADR:         LD A L-1,X       ; Copy hex data to
+                STA STL-1,X     ;  ‘store index’.
+                STA XAML-1,X    ; And to ‘XAM index’.
+                DEX             ; Next of 2 bytes.
+                BNE SETADR      ; Loop unless X=0.
+NXTPRNT:        BNE PRDATA      ; NE means no address to print.
+                LD A 0x8D        ; CR.
+                JSR ECHO        ; Output it.
+                LD A XAMH        ; ‘Examine index’ high-order byte.
+                JSR PRBYTE      ; Output it in hex format.
+                LD A XAML        ; Low-order ‘examine index’ byte.
+                JSR PRBYTE      ; Output it in hex format.
+                LD A #':'+$80    ; ":".
+                JSR ECHO        ; Output it.
+PRDATA:         LD A 0xA0        ; Blank.
+                JSR ECHO        ; Output it.
+                LD A (XAML,X)    ; Get data byte at ‘examine index’.
+                JSR PRBYTE      ; Output it in hex format.
+XAMNEXT:        STX MODE        ; 0->MODE (XAM mode).
+                LD A XAML
+                CMP L           ; Compare ‘examine index’ to hex data.
+                LD A XAMH
+                SBC H
+                BCS TONEXTITEM  ; Not less, so no more data to output.
+                INC XAML
+                BNE MOD8CHK     ; Increment ‘examine index’.
+                INC XAMH
+MOD8CHK:        LD A XAML        ; Check low-order ‘examine index’ byte
+                AND 0x07        ;  For MOD 8=0
+                BPL NXTPRNT     ; Always taken.
+PRBYTE:         PHA             ; Save A for LSD.
+                LSR
+                LSR
+                LSR             ; MSD to LSD position.
+                LSR
+                JSR PRHEX       ; Output hex digit.
+                PLA             ; Restore A.
+PRHEX:          AND 0x0F        ; Mask LSD for hex print.
+                ORA #'0'+$80    ; Add "0".
+                CMP 0xBA        ; Digit?
+                BCC ECHO        ; Yes, output it.
+                ADC 0x06        ; Add offset for letter.
+ECHO:           BIT DSP         ; DA bit (B7) cleared yet?
+                BMI ECHO        ; No, wait for display.
+                STA DSP         ; Output character. Sets DA.
+                RTS             ; Return.
+
+                BRK             ; unused
+                BRK             ; unused
+
+; Interrupt Vectors
+
+                .WORD $0F00     ; NMI
+                .WORD RESET     ; RESET
+                .WORD $0000     ; BRK/IRQ
\ No newline at end of file
diff --git a/instructions.md b/instructions.md
new file mode 100644
index 0000000..5d2a555
--- /dev/null
+++ b/instructions.md
@@ -0,0 +1,437 @@
+# instructions
+
+the base instruction set (some instructions may be undocumented)
+
+table of contents:
+ - [ADD](#add)
+ - [AND](#and)
+ - [CLR](#clr)
+ - [CMP](#cmp)
+ - [CMR](#cmr)
+ - [CRR](#crr)
+ - [DBG](#dbg)
+ - [DIV](#div)
+ - [HALT](#halt)
+ - [JMP](#jmp)
+ - [JMR](#jmr)
+ - [JNZ](#jnz)
+ - [JNZR](#jnzr)
+ - [JZ](#jz)
+ - [LD](#ld)
+ - [LDM](#ldm)
+ - [LDR](#ldr)
+ - [MOD](#mod)
+ - [MOV](#mov)
+ - [MUL](#mul)
+ - [NOT](#not)
+ - [OR](#or)
+ - [PUT](#put)
+ - [RET](#ret)
+ - [SHL](#SHL)
+ - [SHR](#SHR)
+ - [SRM](#srm)
+ - [SRR](#srr)
+ - [STR](#str)
+ - [SUB](#sub)
+ - [SWP](#swp)
+ - [SWPM](#swpm)
+ - [SYS](#sys)
+    + [read (0)](#read-0)
+    + [write (1)](#read-1)
+    + [set raw (2)](#set-raw-2)
+ - [XOR](#xor)
+
+## ADD
+
+add
+
+usage:
+```
+add
+```
+
+adds registers `a` and `b` and puts the output in `c`
+
+## AND
+
+bitwise and
+
+usage:
+```
+and
+```
+
+bitwise and's registers `a` and `b` and puts the output in `c`
+
+
+## CLR
+
+clear return buffer
+
+usage:
+```
+clr
+```
+
+pops the most recent value from the return stack
+
+## CMP
+
+compare
+
+usage:
+```
+cmp (reg1) (value)
+```
+
+compares reg1 and value, if equal, sets return flag to 1, else sets it to 0
+
+## CMR
+
+compare register
+
+usage:
+```
+cmr (reg1) (reg2)
+```
+
+compares reg1 and reg2, if equal, sets return flag to 1, else sets it to 0
+
+## CRR
+
+compare register register
+
+usage:
+```
+cmr (reg1) (reg2) (reg3)
+```
+
+compares reg2 and reg3, if equal, sets reg1 1, else sets it to 0
+
+## DBG
+
+debug
+
+usage:
+```
+dbg (breakpoint name)
+```
+
+dumps ram and halts executing until the user presses enter
+
+## DIV
+
+divide
+
+usage:
+```
+div
+```
+
+divides register `a` by register `b` and stores output in `c`, the output is floored
+
+## HALT
+
+halt
+
+usage:
+```
+halt
+```
+
+halts the CPU
+
+## JMP
+
+jump
+
+usage:
+```
+jmp (line)
+```
+
+jumps to line
+
+## JMR
+
+jump with return
+
+usage:
+```
+jmp (line)
+```
+
+same as jump, but adds the original line to the return stack
+
+## JNZ
+
+jump if non-zero
+
+usage:
+```
+jnz (line)
+```
+
+jump to line if the return flag is not zero
+
+## JNZR
+
+jump if non-zero compare (deprecated)
+
+usage:
+```
+jnzr (reg1) (reg2)
+```
+
+jumps to line at reg1 if reg2 is not zero, deprecated, use [`jnz`](#jnz) and [`cmp`](#cmp) instead
+
+## JZ
+
+jump if zero
+
+usage:
+```
+jnz (line)
+```
+
+jump to line if the return flag is zero
+
+## LD
+
+load from memory
+
+usage:
+```
+ld (reg) (addr)
+```
+
+loads data at address addr into register reg
+
+## LDM
+
+load from memory from memory (deprecated)
+
+usage:
+```
+ldm (reg) (addr)
+```
+
+loads data at address at address addr into register reg, deprecated, use [`ld`](#ld) and [`ldr`](#ldr) instead
+
+## LDR
+
+load from memory at register
+
+usage:
+```
+ld (reg1) (reg2)
+```
+
+loads data at address at reg1 into register reg2
+
+## MOD
+
+modulo
+
+usage:
+```
+mod
+```
+
+does the modulo operation on `a` and `b` and stores in `c`
+
+## MOV
+
+see [`put`](#put)
+
+## MUL
+
+multiply
+
+usage:
+```
+mul
+```
+
+multiplies `a` by `b` and stores in `c`
+
+## NOT
+
+bitwise not
+
+usage:
+```
+not
+```
+
+bitwise not's register `a` and puts the output in `c`
+
+## OR
+
+bitwise or
+
+usage:
+```
+or
+```
+
+bitwise or's registers `a` and `b` and puts the output in `c`
+
+## PUT
+
+put
+
+usage:
+```
+put (reg) (num)
+```
+
+puts num in register reg
+
+## RET
+
+return
+
+usage:
+```
+ret
+```
+
+returns to last value in return stack
+
+## SHL
+
+shift left
+
+usage:
+```
+shl (reg) (by)
+```
+
+shifts the value of `reg` to the left by `by`
+
+## SHR
+
+shift right
+
+usage:
+```
+shr (reg) (by)
+```
+
+shifts the value of `reg` to the right by `by`
+
+## SRM
+
+deprecated
+
+im too lazy to document this, basically the [`ldm`](#ldm) of [`str`](#str), use [`srr`](#srr) instead
+
+## SRR
+
+store register
+
+usage:
+```
+srr (reg1) (reg2)
+```
+
+store value of reg1 at address in reg2
+
+## STR
+
+store
+
+usage:
+```
+srr (reg1) (addr)
+```
+
+store value of reg1 at address addr
+
+## SUB
+
+subtract
+
+usage:
+```
+sub
+```
+
+subtracts register `b` from register `a` and puts the output in `c`
+
+## SWP
+
+swap
+
+usage:
+```
+swp (reg1) (reg2)
+```
+
+swaps registers reg1 and reg2
+
+## SWPM
+
+swap memory
+
+usage:
+```
+swp (reg1) (reg2)
+```
+
+swaps addresses at reg1 and at reg2
+
+## SYS
+
+syscall
+
+usage:
+```
+sys (syscall_id) (...args)
+```
+
+syscall, used for interacting with the system
+
+NOTE: the arguments for the syscall are stored in the registers `a` `b` and `c`, not in the instruction call
+
+syscalls:
+
+### read (0)
+
+```
+sys 0 (fd) (addr)
+```
+
+reads data from file descriptor fd and puts it in ram, starting with addr, the data is null (0x00) terminated
+
+the most common file descriptor you'll see is 0, stdin
+
+also sets register `a` to the length of the read input
+
+### write (1)
+
+```
+sys 1 (fd) (addr)
+```
+
+write data starting from addr (null-terminated) into file descriptor fd
+
+### set raw (2)
+
+```
+sys 1 (raw?)
+```
+
+set tty raw mode
+
+## XOR
+
+bitwise exclusive or
+
+usage:
+```
+xor
+```
+
+bitwise xor's registers `a` and `b` and puts the output in `c`
\ No newline at end of file
diff --git a/instructions/add.ts b/instructions/add.ts
new file mode 100644
index 0000000..93a5018
--- /dev/null
+++ b/instructions/add.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] + this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/and.ts b/instructions/and.ts
new file mode 100644
index 0000000..77a28e0
--- /dev/null
+++ b/instructions/and.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] & this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/clr.ts b/instructions/clr.ts
new file mode 100644
index 0000000..bbbe422
--- /dev/null
+++ b/instructions/clr.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.returnStack.pop();
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/cmp.ts b/instructions/cmp.ts
new file mode 100644
index 0000000..1b2db94
--- /dev/null
+++ b/instructions/cmp.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, val]: number[]) {
+        const r = this.lib.parseReg(reg)
+        this.returnFlag = +(this.registers[r] == +val)
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/cmr.ts b/instructions/cmr.ts
new file mode 100644
index 0000000..c92d939
--- /dev/null
+++ b/instructions/cmr.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.lib.parseReg(reg2)
+        this.returnFlag = +(this.registers[r1] == this.registers[r2])
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/crp.ts b/instructions/crp.ts
new file mode 100644
index 0000000..c334ed5
--- /dev/null
+++ b/instructions/crp.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, val]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.lib.parseReg(reg2)
+        this.registers[r1] = +(this.registers[r2] == val)
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions/crr.ts b/instructions/crr.ts
new file mode 100644
index 0000000..cea6995
--- /dev/null
+++ b/instructions/crr.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.lib.parseReg(reg2)
+        const r3 = this.lib.parseReg(reg3)
+        this.registers[r1] = +(this.registers[r2] == this.registers[r3])
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions/dbg.ts b/instructions/dbg.ts
new file mode 100644
index 0000000..6781fbf
--- /dev/null
+++ b/instructions/dbg.ts
@@ -0,0 +1,13 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [msg]: string[]) {
+        console.log(msg, this.mem, this.registers, this.returnFlag, this.returnStack);
+        const b = new Uint8Array(1);
+        Deno.stdin.readSync(b)
+        if (b[0] == 'c'.charCodeAt(0)) {
+            this.programPointer = 0xFFFF - 1
+        }
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions/dec.ts b/instructions/dec.ts
new file mode 100644
index 0000000..df46769
--- /dev/null
+++ b/instructions/dec.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, by]: number[]) {
+        const r = this.lib.parseReg(reg);
+        this.registers[r] -= by
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/decr.ts b/instructions/decr.ts
new file mode 100644
index 0000000..12e7fd9
--- /dev/null
+++ b/instructions/decr.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.registers[r1] -= this.registers[r2]
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/div.ts b/instructions/div.ts
new file mode 100644
index 0000000..dbad7e1
--- /dev/null
+++ b/instructions/div.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = Math.floor(this.registers[0] / this.registers[1])
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/halt.ts b/instructions/halt.ts
new file mode 100644
index 0000000..4685f2b
--- /dev/null
+++ b/instructions/halt.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        // this.programPointer = 0xFFFF - 1
+        this.halted = true
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/inc.ts b/instructions/inc.ts
new file mode 100644
index 0000000..180546e
--- /dev/null
+++ b/instructions/inc.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, by]: number[]) {
+        const r = this.lib.parseReg(reg);
+        this.registers[r] += by
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/incr.ts b/instructions/incr.ts
new file mode 100644
index 0000000..5f1d529
--- /dev/null
+++ b/instructions/incr.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.registers[r1] += this.registers[r2]
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/jmp.ts b/instructions/jmp.ts
new file mode 100644
index 0000000..00db338
--- /dev/null
+++ b/instructions/jmp.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [addr]: string[]) {
+        this.programPointer = Number(addr) - 1
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions/jmr.ts b/instructions/jmr.ts
new file mode 100644
index 0000000..25f5334
--- /dev/null
+++ b/instructions/jmr.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [addr]: string[]) {
+        this.returnStack.push(this.programPointer)
+        this.programPointer = Number(addr) - 1
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions/jnz.ts b/instructions/jnz.ts
new file mode 100644
index 0000000..e5b539f
--- /dev/null
+++ b/instructions/jnz.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [addr]: string[]) {
+        if (this.returnFlag == 0) return;
+        this.programPointer = +addr - 1
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions/jnzr.ts b/instructions/jnzr.ts
new file mode 100644
index 0000000..00f1569
--- /dev/null
+++ b/instructions/jnzr.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.lib.parseReg(reg2)
+        if (this.registers[r1] == 0) return;
+        this.programPointer = this.registers[r2] - 1
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/jz.ts b/instructions/jz.ts
new file mode 100644
index 0000000..0e105b3
--- /dev/null
+++ b/instructions/jz.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [addr]: string[]) {
+        if (this.returnFlag != 0) return;
+        this.programPointer = +addr - 1
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions/ld.ts b/instructions/ld.ts
new file mode 100644
index 0000000..977f343
--- /dev/null
+++ b/instructions/ld.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, addr]: number[]) {
+        const r = this.lib.parseReg(reg)
+        this.registers[r] = this.getMem(Number(addr))
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/ldm.ts b/instructions/ldm.ts
new file mode 100644
index 0000000..c82425a
--- /dev/null
+++ b/instructions/ldm.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, addr]: number[]) {
+        this.registers[this.lib.parseReg(reg)] = this.getMem(this.getMem(Number(addr)))
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/ldr.ts b/instructions/ldr.ts
new file mode 100644
index 0000000..724b94c
--- /dev/null
+++ b/instructions/ldr.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        this.registers[this.lib.parseReg(reg1)] = this.getMem(this.registers[this.lib.parseReg(reg2)])
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/mod.ts b/instructions/mod.ts
new file mode 100644
index 0000000..24b96d5
--- /dev/null
+++ b/instructions/mod.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] % this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/mul.ts b/instructions/mul.ts
new file mode 100644
index 0000000..b625a07
--- /dev/null
+++ b/instructions/mul.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] * this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/not.ts b/instructions/not.ts
new file mode 100644
index 0000000..6416a5c
--- /dev/null
+++ b/instructions/not.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = ~this.registers[0]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/or.ts b/instructions/or.ts
new file mode 100644
index 0000000..5a8b593
--- /dev/null
+++ b/instructions/or.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] | this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/put.ts b/instructions/put.ts
new file mode 100644
index 0000000..a35806e
--- /dev/null
+++ b/instructions/put.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, data]: number[]) {
+        const r = this.lib.parseReg(reg)
+        this.registers[r] = Number(data) ?? 0
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/ret.ts b/instructions/ret.ts
new file mode 100644
index 0000000..6a42313
--- /dev/null
+++ b/instructions/ret.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        const ret = this.returnStack.pop();
+        if (ret == undefined) throw 'whar'
+        this.programPointer = ret
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/sbc.ts b/instructions/sbc.ts
new file mode 100644
index 0000000..928aa61
--- /dev/null
+++ b/instructions/sbc.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.registers[r1] -= this.registers[r2] - this.returnFlag
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/shl.ts b/instructions/shl.ts
new file mode 100644
index 0000000..68345bb
--- /dev/null
+++ b/instructions/shl.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, by]: number[]) {
+        const r = this.lib.parseReg(reg);
+        this.registers[r] = this.registers[r] << by
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/shr.ts b/instructions/shr.ts
new file mode 100644
index 0000000..15e9345
--- /dev/null
+++ b/instructions/shr.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, by]: number[]) {
+        const r = this.lib.parseReg(reg);
+        this.registers[r] = this.registers[r] >> by
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/srm.ts b/instructions/srm.ts
new file mode 100644
index 0000000..b3c71fa
--- /dev/null
+++ b/instructions/srm.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, addr]: number[]) {
+        this.setMem(this.getMem(Number(addr)), this.registers[this.lib.parseReg(reg)])
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/srr.ts b/instructions/srr.ts
new file mode 100644
index 0000000..0a7e5c6
--- /dev/null
+++ b/instructions/srr.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.registers[this.lib.parseReg(reg2)]
+        this.setMem(Number(r2), this.registers[r1] & 0xFFFF)
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/str.ts b/instructions/str.ts
new file mode 100644
index 0000000..bdcae63
--- /dev/null
+++ b/instructions/str.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, addr]: number[]) {
+        const r = this.lib.parseReg(reg)
+        this.setMem(Number(addr), this.registers[r] & 0xFFFF)
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/sub.ts b/instructions/sub.ts
new file mode 100644
index 0000000..8e4d894
--- /dev/null
+++ b/instructions/sub.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] - this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/swp.ts b/instructions/swp.ts
new file mode 100644
index 0000000..48ee9b6
--- /dev/null
+++ b/instructions/swp.ts
@@ -0,0 +1,13 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.lib.parseReg(reg2)
+        const data1 = Number(this.registers[r1])
+        const data2 = Number(this.registers[r2])
+        this.registers[r1] = data2
+        this.registers[r2] = data1
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/swpm.ts b/instructions/swpm.ts
new file mode 100644
index 0000000..f4856a2
--- /dev/null
+++ b/instructions/swpm.ts
@@ -0,0 +1,13 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const addr1 = this.registers[this.lib.parseReg(reg1)]
+        const addr2 = this.registers[this.lib.parseReg(reg2)]
+        const data1 = 0 + this.getMem(+addr1)
+        const data2 = 0 + this.getMem(+addr2)
+        this.setMem(+addr1, data2)
+        this.setMem(+addr2, data1)
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions/sys.ts b/instructions/sys.ts
new file mode 100644
index 0000000..5131bf2
--- /dev/null
+++ b/instructions/sys.ts
@@ -0,0 +1,55 @@
+// deno-lint-ignore-file no-case-declarations no-process-globals
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        switch (this.registers[0]) {
+            case 0:
+                switch (this.registers[1]) {
+                    case 0:
+                        const data = new Uint8Array(1024)
+                        const len = Deno.stdin.readSync(data) ?? 0
+                        let i = 0;
+                        while (i < len) {
+                            this.mem[this.registers[2] + i] = data[i]
+                            i++
+                        }
+                        this.registers[0] = len
+                        this.mem[this.registers[2] + i] = 0
+                        break;
+
+                    default:
+                        throw 'unknown fd'
+                }
+                break;
+            case 1:
+                const writeBuff = [];
+                let i = this.registers[2];
+                while (this.mem[i] != 0 && i <= this.mem.length) {
+                    writeBuff.push(this.mem[i]);
+                    i++
+                }
+                switch (this.registers[1]) {
+                    case 1:
+                        process.stdout.write(writeBuff.map(a => String.fromCharCode(a)).join(''))
+                        break;
+
+                    case 2:
+                        process.stderr.write(writeBuff.map(a => String.fromCharCode(a)).join(''))
+                        break;
+
+                    default:
+                        throw 'unknown fd'
+                }
+                break;
+            
+            case 2:
+                Deno.stdin.setRaw(this.registers[1] ? true : false);
+                break;
+
+            default:
+                throw 'unknown syscall id ' + this.registers[0]
+        }
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions/xor.ts b/instructions/xor.ts
new file mode 100644
index 0000000..4cccecd
--- /dev/null
+++ b/instructions/xor.ts
@@ -0,0 +1,8 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        this.registers[2] = this.registers[0] ^ this.registers[1]
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions_new/add.ts b/instructions_new/add.ts
new file mode 100644
index 0000000..5d211d3
--- /dev/null
+++ b/instructions_new/add.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] + this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] + this.registers[r3]
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/and.ts b/instructions_new/and.ts
new file mode 100644
index 0000000..12db601
--- /dev/null
+++ b/instructions_new/and.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.registers[r1] = this.registers[r2] & this.registers[r3];
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/cmp.ts b/instructions_new/cmp.ts
new file mode 100644
index 0000000..f97322a
--- /dev/null
+++ b/instructions_new/cmp.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.returnFlag = +(this.registers[r1] == this.registers[r2]);
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/cmr.ts b/instructions_new/cmr.ts
new file mode 100644
index 0000000..a83b46c
--- /dev/null
+++ b/instructions_new/cmr.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.registers[r1] = +(this.registers[r2] == this.registers[r3]);
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/div.ts b/instructions_new/div.ts
new file mode 100644
index 0000000..c78cd93
--- /dev/null
+++ b/instructions_new/div.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] / this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] / this.registers[r3]
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/halt.ts b/instructions_new/halt.ts
new file mode 100644
index 0000000..4685f2b
--- /dev/null
+++ b/instructions_new/halt.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        // this.programPointer = 0xFFFF - 1
+        this.halted = true
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions_new/jmp.ts b/instructions_new/jmp.ts
new file mode 100644
index 0000000..f3bbc79
--- /dev/null
+++ b/instructions_new/jmp.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        this.programPointer = this.registers[r1]
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/jmr.ts b/instructions_new/jmr.ts
new file mode 100644
index 0000000..f7b0c00
--- /dev/null
+++ b/instructions_new/jmr.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        this.returnStack.push(this.programPointer);
+        this.programPointer = this.registers[r1];
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/jnz.ts b/instructions_new/jnz.ts
new file mode 100644
index 0000000..d600f59
--- /dev/null
+++ b/instructions_new/jnz.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1]: number[]) {
+        if (this.returnFlag == 0) return;
+        const r1 = this.lib.parseReg(reg1);
+        this.programPointer = this.registers[r1]
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/jz.ts b/instructions_new/jz.ts
new file mode 100644
index 0000000..0d4f64c
--- /dev/null
+++ b/instructions_new/jz.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1]: number[]) {
+        if (this.returnFlag != 0) return;
+        const r1 = this.lib.parseReg(reg1);
+        this.programPointer = this.registers[r1]
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/ld.ts b/instructions_new/ld.ts
new file mode 100644
index 0000000..8d6c30d
--- /dev/null
+++ b/instructions_new/ld.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.returnFlag = +(this.getMem(this.registers[r2]) != 0);
+        this.registers[r1] = this.getMem(this.registers[r2])
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/mod.ts b/instructions_new/mod.ts
new file mode 100644
index 0000000..8f1a343
--- /dev/null
+++ b/instructions_new/mod.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] % this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] % this.registers[r3]
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/mov.ts b/instructions_new/mov.ts
new file mode 100644
index 0000000..a35806e
--- /dev/null
+++ b/instructions_new/mov.ts
@@ -0,0 +1,9 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg, data]: number[]) {
+        const r = this.lib.parseReg(reg)
+        this.registers[r] = Number(data) ?? 0
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/mul.ts b/instructions_new/mul.ts
new file mode 100644
index 0000000..bf3f12c
--- /dev/null
+++ b/instructions_new/mul.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] * this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] * this.registers[r3]
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/not.ts b/instructions_new/not.ts
new file mode 100644
index 0000000..241897a
--- /dev/null
+++ b/instructions_new/not.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.returnFlag = +((~this.registers[r1]) != 0);
+        this.registers[r1] = ~this.registers[r2];
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/or.ts b/instructions_new/or.ts
new file mode 100644
index 0000000..bd7cc7e
--- /dev/null
+++ b/instructions_new/or.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] | this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] | this.registers[r3];
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/pop.ts b/instructions_new/pop.ts
new file mode 100644
index 0000000..83ece88
--- /dev/null
+++ b/instructions_new/pop.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1]: number[]) {
+        if (!this.getMem(0x7000)) throw 'no stack pointer';
+        if (this.getMem(0x7001) == 0) throw 'stack underflow';
+        const r1 = this.lib.parseReg(reg1);
+        this.registers[r1] = this.getMem(this.getMem(0x7001) + 1);
+        this.setMem(0x7001, this.getMem(0x7001) - 1)
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/push.ts b/instructions_new/push.ts
new file mode 100644
index 0000000..b9dd718
--- /dev/null
+++ b/instructions_new/push.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1]: number[]) {
+        if (!this.getMem(0x7000)) throw 'no stack pointer';
+        if (this.getMem(0x7001) == 256) throw 'stack overflow';
+        const r1 = this.lib.parseReg(reg1);
+        this.setMem(this.getMem(0x7000) + this.getMem(0x7001), this.registers[r1])
+        this.setMem(0x7001, this.getMem(0x7001) + 1)
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/ret.ts b/instructions_new/ret.ts
new file mode 100644
index 0000000..04b5cc3
--- /dev/null
+++ b/instructions_new/ret.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC) {
+        const returnAddr = this.returnStack.pop();
+        if (!returnAddr) throw 'return stack empty';
+        this.programPointer = returnAddr;
+    },
+    args: 1
+}
\ No newline at end of file
diff --git a/instructions_new/shl.ts b/instructions_new/shl.ts
new file mode 100644
index 0000000..16bb382
--- /dev/null
+++ b/instructions_new/shl.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.returnFlag = +((this.registers[r1] << this.registers[r2]) != 0);
+        this.registers[r1] <<= this.registers[r2]
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/shr.ts b/instructions_new/shr.ts
new file mode 100644
index 0000000..09bf005
--- /dev/null
+++ b/instructions_new/shr.ts
@@ -0,0 +1,11 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.returnFlag = +((this.registers[r1] >> this.registers[r2]) != 0);
+        this.registers[r1] >>= this.registers[r2]
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/str.ts b/instructions_new/str.ts
new file mode 100644
index 0000000..aa4c2d5
--- /dev/null
+++ b/instructions_new/str.ts
@@ -0,0 +1,10 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        this.setMem(this.registers[r1], this.registers[r2]);
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/sub.ts b/instructions_new/sub.ts
new file mode 100644
index 0000000..c7b4e94
--- /dev/null
+++ b/instructions_new/sub.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] - this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] - this.registers[r3]
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/instructions_new/swp.ts b/instructions_new/swp.ts
new file mode 100644
index 0000000..7d07aea
--- /dev/null
+++ b/instructions_new/swp.ts
@@ -0,0 +1,15 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2]: number[]) {
+        const r1 = this.lib.parseReg(reg1)
+        const r2 = this.lib.parseReg(reg2);
+        [this.registers[r1], this.registers[r2]] =
+            [this.registers[r2], this.registers[r1]]
+        // const data1 = Number(this.registers[r1])
+        // const data2 = Number(this.registers[r2])
+        // this.registers[r1] = data2
+        // this.registers[r2] = data1
+    },
+    args: 2
+}
\ No newline at end of file
diff --git a/instructions_new/sys.ts b/instructions_new/sys.ts
new file mode 100644
index 0000000..fc27af9
--- /dev/null
+++ b/instructions_new/sys.ts
@@ -0,0 +1,60 @@
+// deno-lint-ignore-file no-case-declarations no-process-globals
+import { PC } from "../pc.ts";
+
+declare global {
+    const process: any;
+}
+
+export default {
+    function(this: PC) {
+        if (typeof process == 'undefined') throw 'process global is undefined';
+        switch (this.registers[0]) {
+            case 0:
+                switch (this.registers[1]) {
+                    case 0:
+                        const data = new Uint8Array(1024)
+                        const len = Deno.stdin.readSync(data) ?? 0
+                        let i = 0;
+                        while (i < len) {
+                            this.mem[this.registers[2] + i] = data[i]
+                            i++
+                        }
+                        this.registers[0] = len
+                        this.mem[this.registers[2] + i] = 0
+                        break;
+
+                    default:
+                        throw 'unknown fd'
+                }
+                break;
+            case 1:
+                const writeBuff = [];
+                let i = this.registers[2];
+                while (this.mem[i] != 0 && i <= this.mem.length) {
+                    writeBuff.push(this.mem[i]);
+                    i++
+                }
+                switch (this.registers[1]) {
+                    case 1:
+                        process.stdout.write(writeBuff.map(a => String.fromCharCode(a)).join(''))
+                        break;
+
+                    case 2:
+                        process.stderr.write(writeBuff.map(a => String.fromCharCode(a)).join(''))
+                        break;
+
+                    default:
+                        throw 'unknown fd'
+                }
+                break;
+            
+            case 2:
+                Deno.stdin.setRaw(this.registers[1] ? true : false);
+                break;
+
+            default:
+                throw 'unknown syscall id ' + this.registers[0]
+        }
+    },
+    args: 0
+}
\ No newline at end of file
diff --git a/instructions_new/xor.ts b/instructions_new/xor.ts
new file mode 100644
index 0000000..135e1cf
--- /dev/null
+++ b/instructions_new/xor.ts
@@ -0,0 +1,12 @@
+import { PC } from "../pc.ts";
+
+export default {
+    function(this: PC, [reg1, reg2, reg3]: number[]) {
+        const r1 = this.lib.parseReg(reg1);
+        const r2 = this.lib.parseReg(reg2);
+        const r3 = this.lib.parseReg(reg3);
+        this.returnFlag = +((this.registers[r2] ^ this.registers[r3]) != 0);
+        this.registers[r1] = this.registers[r2] ^ this.registers[r3];
+    },
+    args: 3
+}
\ No newline at end of file
diff --git a/lib.ts b/lib.ts
new file mode 100644
index 0000000..a1cd815
--- /dev/null
+++ b/lib.ts
@@ -0,0 +1,5 @@
+export function parseReg(arg: number): number {
+    if (!'abcd'.split('').includes(String.fromCharCode(arg).toLowerCase()))
+        throw `invalid register "${String.fromCharCode(arg)}"`;
+    return 'abcd'.split('').indexOf(String.fromCharCode(arg).toLowerCase())
+}
\ No newline at end of file
diff --git a/pc.ts b/pc.ts
new file mode 100644
index 0000000..a007189
--- /dev/null
+++ b/pc.ts
@@ -0,0 +1,68 @@
+import * as lib from "./lib.ts";
+type Registers = [number, number, number, number]
+export class PC {
+    registers: Registers = new Array<number>(4).fill(0) as Registers
+    regNames: string = 'abcd'
+    halted: boolean = false
+    mem = new Array<number>(2**16).fill(0)
+    getSegment: undefined | ((segment: number) => Uint16Array) = undefined;
+    getMem(addr: number): number {
+        if (addr < 0 || addr > 2**16)
+            throw 'invalid address';
+        //TODO - memory mapping
+        return this.mem[addr];
+    }
+    setMem(addr: number, data: number) {
+        if (this.getSegment && addr == 0x7cff) {
+            const segment = this.getSegment(data)
+            for (let i = 0; i < 512; i++) {
+                this.mem[0x7d00 + i] = segment.length > i ? segment[i] : 0;
+            }
+            return;
+        }
+        if (addr >= 0x7d00 && addr <= 0x7fff && this.getSegment) {
+            return;
+        }
+        this.mem[addr] = Math.floor(data) % 2**16
+    }
+    programPointer: number = 0;
+    lib = lib
+    returnFlag = 0;
+    returnStack: number[] = []
+    // the instruction set, in no particular order :3
+    instructions: Record<number, string> = {
+        0:  'mov',
+        1:  'swp',
+        2:  'ld',
+        3:  'str',
+        4:  'add',
+        5:  'sub',
+        6:  'mul',
+        7:  'div',
+        8:  'mod',
+        9:  'shl',
+        10: 'shr',
+        11: 'cmp',
+        12: 'cmr',
+        13: 'and',
+        14: 'or',
+        15: 'xor',
+        16: 'not',
+        17: 'push',
+        18: 'pop',
+        19: 'halt',
+        20: 'sys', // extra
+        21: 'jmp',
+        22: 'jnz',
+        23: 'jz',
+        24: 'jmr',
+        25: 'ret',
+        
+        31: 'end'
+    }
+    constructor(diskSupport = false) {
+        if (diskSupport) {
+            this.mem[0x7cff] = (2**16) - 1
+        }
+    }
+}
\ No newline at end of file
diff --git a/ramgen.ts b/ramgen.ts
new file mode 100644
index 0000000..f6e419f
--- /dev/null
+++ b/ramgen.ts
@@ -0,0 +1,116 @@
+import { PC } from "./pc.ts";
+const pc = new PC()
+
+const commands = []
+const commandData: Record<string, any> = {}
+
+const dir = Deno.readDirSync('instructions_new');
+
+for (const filename of dir) {
+    commands.push(filename.name.replace(/\..*?$/g, ''))
+    commandData[filename.name.replace(/\..*?$/g, '')] = (await import('./instructions_new/' + filename.name)).default
+}
+
+commands.push('end')
+
+commandData.end = {
+    args: 0
+}
+
+interface ObjectFile {
+    // number is the ammount of bytes to skip
+    code: (string | number)[],
+    offset: number,
+    // line number, data
+    data: [number, number[]][]
+}
+
+// console.log(commands, commands.length, (commands.length - 1).toString(16))
+
+const object: ObjectFile = JSON.parse(new TextDecoder().decode(Deno.readFileSync('code.o')))
+
+const code = object.code
+
+const offset = object.offset ?? 2**16 / 2
+
+const ram = []
+
+const instructions = []
+
+for (const element of code) {
+    if (typeof element == 'number') {
+        instructions.push(element)
+        continue;
+    }
+    const [command, ...args] = element.split(' ');
+    switch (command) {
+        case '.hex':
+            instructions.push([parseInt(args[0], 16)]);
+            continue;
+        // deno-lint-ignore no-case-declarations
+        case '.str':
+            const str = [...element.matchAll(/"(.*?)(?<!\\)"/g)][0][1].replaceAll('\\"', '"')
+            instructions.push(new Array(str.length).fill(0).map((_, i) => str.charCodeAt(i)));
+            continue;
+    }
+    const parsedArgs = args.map(arg => {
+        if (arg.startsWith('$')) return arg // line numbers can pass
+        if (arg.match(/^\[.*\]$/)) return arg // line numbers can pass
+        if (!isNaN(+arg)) {
+            // make sure its a uint16
+            return Math.floor(+arg) & 0xFFFF
+        }
+        arg = arg.toLowerCase();
+        if (!pc.regNames.split('').includes(arg)) throw 'whar '+arg
+        return arg
+    })
+    const inst = Object.entries(pc.instructions).find(([_, b]) => b == command);
+    if (!inst) throw 'erm,, what the sigma ' + command + ' (' + inst + ')'
+    if (!commandData[command]) throw 'no command data for ' + command + ' (' + inst + ')'
+    if (commandData[command].args != args.length)
+        throw `mismatch of ${command} arg length ${commandData[command].args} != ${args.length}`
+    instructions.push([+inst[0], ...parsedArgs])
+}
+
+const instructionAddresses: number[] = [];
+
+let addr = offset;
+for (const instr of instructions) {
+    instructionAddresses.push(addr);
+    addr += typeof instr == 'number' ? instr : instr.length
+}
+
+let i = 0
+for (const instr of instructions) {
+    // console.log(instr, Array.isArray(instr) ? instr[0].toString(16) : null)
+    if (typeof instr == 'number') {
+        // console.log(ram.length, instr, new Array<number>(instr).fill(0))
+        ram.push(...new Array<number>(instr).fill(0))
+        continue;
+    }
+    const newInstr: number[] = instr.map<number>(i => {
+        if (typeof i !== 'string') return i;
+        const m = i.match(/^\[(.*)\]$/)
+        if (m) {
+            const ln = m[1]
+            if (!instructionAddresses[+ln]) throw 'a '+i
+            // console.log(i, instructionAddresses[+i.replace('$', '')])
+            return instructionAddresses[+ln]
+        }
+        if (!i.startsWith('$')) return i.charCodeAt(0);
+        if (!instructionAddresses[+i.replace('$', '')]) throw 'a '+i
+        // console.log(i, instructionAddresses[+i.replace('$', '')])
+        return instructionAddresses[+i.replace('$', '')]
+    })
+    // console.log(instructionAddresses[i], (instructionAddresses[i] * 2).toString(16), commands[newInstr[0]], newInstr)
+    ram.push(...newInstr)
+    i++
+}
+
+
+for (const element of object.data) {
+    // console.log(instructionAddresses[element[0]] - offset, element[0], element[1])
+    ram.splice(instructionAddresses[element[0]] - offset, element[1].length, ...element[1])
+}
+
+Deno.writeFileSync(Deno.args[0] ?? 'iram.bin', Uint8Array.from(ram.map(a => [a & 0x00FF, (a & 0xFF00) >> 8]).flatMap(([a, b]) => [a, b])))
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..047d8c0
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,19 @@
+# shitPC
+
+an emulator for a fictional 16 bit computer thingy
+
+the system has:
+
+- 3 registers: A, B and C (16-bit)
+
+- 65535 addressable locations (each one storing 16 bits)
+
+- interrupt support
+
+- basic I/O
+
+- its own assembly language
+
+- disk support
+
+see [instructions.md](instructions.md) to see the documentation for the instructions or [assembler.md](assembler.md) to see the documentation for the assembler
\ No newline at end of file
diff --git a/redme.txt b/redme.txt
new file mode 100644
index 0000000..73e3813
--- /dev/null
+++ b/redme.txt
@@ -0,0 +1,5 @@
+deno -A assembler.ts && deno -A ramgen.ts && hexdump -C iram.bin
+this shit compiles
+
+deno -A runtime_new.ts
+this shit runs
\ No newline at end of file
diff --git a/runtime.ts b/runtime.ts
new file mode 100644
index 0000000..cde4b95
--- /dev/null
+++ b/runtime.ts
@@ -0,0 +1,55 @@
+import { PC } from "./pc.ts";
+
+class Runtime {
+    pc: PC = new PC()
+    instructions: Map<string, (this: PC, argv: string[]) => void> = new Map()
+
+    addInstruction(name: string, instruction: (this: PC, argv: string[]) => void) {
+        this.instructions.set(name, instruction)
+    }
+
+    run(line: string) {
+        line = line.replace(/\s*;.*$/gm, '')
+        if (!line) return;
+        const [instr, ...argv] = line.split(' ')
+        const instructionId = instr.toLowerCase()
+        if (!this.instructions.has(instructionId))
+            throw 'unknown instruction';
+        const instruction = this.instructions.get(instructionId);
+        if (!instruction)
+            throw 'unknown instruction';
+        instruction.call(this.pc, argv)
+    }
+}
+
+const runtime = new Runtime()
+
+const dir = Deno.readDirSync('instructions');
+
+for (const filename of dir) {
+    runtime.addInstruction(filename.name.replace(/\..*?$/g, ''),
+        (await import('./instructions/'+filename.name)).default)
+}
+
+const code = new TextDecoder().decode(Deno.readFileSync('code.p')).split('\n')
+
+runtime.pc.programPointer = 0
+while (runtime.pc.programPointer < code.length) {
+    const line = code[runtime.pc.programPointer]
+    try {
+        runtime.run(line)
+        // console.debug('0'.repeat(4 - String(runtime.pc.programPointer).length) +
+        //     runtime.pc.programPointer,
+        //     runtime.pc.registers, line)
+    } catch (error) {
+        console.error(error, 'at', line);
+        throw 'Unexpected error while running program'
+    }
+    runtime.pc.programPointer++
+}
+
+console.debug('end of execution, dumping ram', runtime.pc.mem)
+Deno.writeFileSync('ram.bin', Uint8Array.from(runtime.pc.mem.map(a => [a & 0x00FF, (a & 0xFF00) >> 8]).flatMap(([a, b]) => [a, b])))
+new Deno.Command('hexdump', {
+    args: ['-C', 'ram.bin']
+}).spawn()
\ No newline at end of file
diff --git a/runtime_new.ts b/runtime_new.ts
new file mode 100644
index 0000000..f0045d6
--- /dev/null
+++ b/runtime_new.ts
@@ -0,0 +1,134 @@
+import { PC } from "./pc.ts";
+
+type instruction = { function: (this: PC, argv: number[]) => void, args: number }
+
+class Runtime {
+    pc: PC = new PC(true)
+    instructions: Record<string, instruction> = {}
+    instructionNames: string[] = []
+
+    addInstruction(name: string, instruction: instruction) {
+        this.instructionNames.push(name)
+        this.instructions[name] = instruction
+    }
+
+    run(line: number[]) {
+        const instructionId = this.pc.instructions[line.shift() ?? -1]
+        if (instructionId == undefined || !this.instructions[instructionId])
+            throw 'unknown instruction (1)';
+        const instruction = this.instructions[instructionId];
+        if (!instruction)
+            throw 'unknown instruction (2)';
+        try {
+            instruction.function.call(this.pc, line)
+        } catch (error) {
+            console.error(error, 'at', this.pc.programPointer, instructionId)
+        }
+    }
+}
+
+const disk = [...Deno.readFileSync('disk.img')].reduce<number[]>((result, value, index, array) => {
+    if (index % 2 === 0) {
+        result.push(value | (array[index + 1] << 8))
+    }
+    return result;
+}, [])
+
+const runtime = new Runtime()
+
+runtime.pc.getSegment = function getSegment(segment: number): Uint16Array {
+    const seg = disk.slice(segment * 512, (segment + 1) * 512);
+    console.log(`getSegment( ${segment} ):`, seg)
+    return Uint16Array.from(seg.fill(seg.length, 512))
+}
+
+const dir = Deno.readDirSync('instructions_new');
+
+for (const filename of dir) {
+    runtime.addInstruction(filename.name.replace(/\..*?$/g, ''),
+        (await import('./instructions_new/' + filename.name)).default)
+}
+
+runtime.addInstruction('end', { function: () => { }, args: 0 })
+
+const iram = Deno.readFileSync("iram.bin")
+
+runtime.pc.mem = runtime.pc.mem.toSpliced(65534 / 2 + 1, 0, ...[...iram].reduce<number[]>((result, value, index, array) => {
+    if (index % 2 === 0) {
+        result.push(value | (array[index + 1] << 8))
+    }
+    return result;
+}, []))
+
+runtime.pc.programPointer = 65536 / 2
+
+const haltEvents = new EventTarget()
+
+function waitUntilNotInterrupted(): Promise<void> {
+    return new Promise((resolve) => {
+        const callback = () => {
+            resolve()
+            haltEvents.removeEventListener('unHalted', callback)
+        }
+        haltEvents.addEventListener('unHalted', callback)
+    })
+}
+
+function gotoInterrupt() {
+    // console.log("INTERRUPT!", runtime.pc.mem[0x7000])
+    if (!runtime.pc.mem[0x7000])
+        return;
+    runtime.pc.halted = false
+    haltEvents.dispatchEvent(new Event('unHalted'));
+    runtime.pc.returnStack.push(runtime.pc.programPointer - 1);
+    runtime.pc.programPointer = runtime.pc.mem[0x7000]
+}
+
+const interruptInterval = setInterval(gotoInterrupt, 10)
+
+const endInst = (Object.entries(runtime.pc.instructions) as [unknown, string][] as [number, string][])
+    .find(([_, b]: [number, string]) => b == 'end')
+if (!endInst) throw 'where the fuck is the end instruction'
+const endInstId = endInst[0];
+
+
+let c = 0
+while (
+    runtime.pc.mem[runtime.pc.programPointer] != endInstId &&
+    runtime.pc.programPointer != 0xFFFF - 1) {
+    try {
+        const definition = Object.entries(runtime.pc.instructions).find(([a]) => +a == runtime.pc.mem[runtime.pc.programPointer])
+        if (!definition || !definition[1]) throw `what the fuck is that (unknown instruction)
+at ${runtime.pc.programPointer} (${runtime.pc.programPointer.toString(16)}/${(runtime.pc.programPointer * 2).toString(16)}/${(runtime.pc.programPointer * 2 - (2 ** 16)).toString(16)})
+instruction: ${runtime.pc.mem[runtime.pc.programPointer]}`
+        const instruction = definition[1]
+        runtime.pc.programPointer++
+        // console.debug(instruction, runtime.instructions, definition)
+        const args = [];
+        if (Deno.args.includes('-d'))
+            console.debug(runtime.pc.programPointer, definition, instruction, runtime.pc.mem[runtime.pc.programPointer + 1])
+        while (args.length < runtime.instructions[instruction].args) {
+            args.push(runtime.pc.mem[runtime.pc.programPointer])
+            runtime.pc.programPointer++
+        }
+        runtime.run([+definition[0], ...args])
+        // runtime.pc.programPointer++
+        c++
+    } catch (error) {
+        console.error(error);
+        break;
+    }
+    if (runtime.pc.halted) {
+        await waitUntilNotInterrupted()
+    }
+}
+
+clearInterval(interruptInterval)
+
+if (Deno.args.includes('-d'))
+    console.debug(Object.values(runtime.pc.instructions))
+console.debug('end of execution, dumping ram', runtime.pc.mem)
+Deno.writeFileSync('ram.bin', Uint8Array.from(runtime.pc.mem.map(a => [a & 0x00FF, (a & 0xFF00) >> 8]).flatMap(([a, b]) => [a, b])))
+new Deno.Command('hexdump', {
+    args: ['-C', 'ram.bin']
+}).spawn()
diff --git a/shit-instruction-set-2 b/shit-instruction-set-2
new file mode 100644
index 0000000..08864fb
--- /dev/null
+++ b/shit-instruction-set-2
@@ -0,0 +1,62 @@
+# the SHIT PC(R) INSTRUCTION SET(TM) 2 #
+
+> format:
+>
+> OPCODE[ARGS] -> (OUT/VOID)
+
+## Math ##
+```
+ADD[REG1, REG2, REG3] -> (REG1) Add
+SUB[REG1, REG2, REG3] -> (REG1) Subtract
+MUL[REG1, REG2, REG3] -> (REG1) Multiply
+DIV[REG1, REG2, REG3] -> (REG1) Divide
+MOD[REG1, REG2, REG3] -> (REG1) Modulo
+SHL[REG1, REG2]       -> (REG1) Shift left
+SHR[REG1, REG2]       -> (REG1) Shift right
+CMP[REG1, REG2]       -> (VOID) Compare
+CMR[REG1, REG2, REG3] -> (REG1) Compare Register
+AND[REG1, REG2, REG3] -> (REG1) Logical AND
+OR[REG1, REG2, REG3]  -> (REG1) Logical OR
+XOR[REG1, REG2, REG3] -> (REG1) Logical XOR
+NOT[REG1, REG2]       -> (REG1) Logical NOT
+```
+## Registers ##
+```
+MOV[REG, VAL]          -> (REG) Move
+SWP[REG1, REG2] -> (REG1, REG2) Swap register
+```
+## Memory ##
+```
+LD[REG1, REG2]   -> (REG1) Load from address
+STR[REG1, REG2] -> ($REG1) Set address
+```
+## Jumping & stuff ##
+```
+JMP[REG] -> (VOID) Jump to address
+JNZ[REG] -> (VOID) Jump if flag is non-zero
+JZ[REG]  -> (VOID) Jump if flag is zero
+JMR[REG] -> (VOID) Jump with return
+RET[]    -> (VOID) Return
+```
+## Stack ##
+> [!NOTE]
+> The stack limit is 256, and it is only enabled once $7000h is set to a stack address
+>
+> $7001h has the pointer
+> 
+> Keep in mind that the stack pointer goes **down** from that address
+```
+PUSH[REG] -> (VOID) Push to stack
+POP[REG]  -> (REG)  Pop from stack
+```
+## System ##
+```
+HALT[] -> (VOID) Halt the processor
+```
+
+#### extra ####
+
+this might get replaced with a thing yin the ram in the future possibly
+```
+SYS[TYPE, ...] -> (VOID) Systemcall
+```
\ No newline at end of file
diff --git a/test.ts b/test.ts
new file mode 100644
index 0000000..ff6e23c
--- /dev/null
+++ b/test.ts
@@ -0,0 +1,3 @@
+const data = new Uint8Array(1024)
+console.log(Deno.stdin.readSync(data), data)
+
diff --git a/the_e_programming_language/ast.json b/the_e_programming_language/ast.json
new file mode 100644
index 0000000..faf9b67
--- /dev/null
+++ b/the_e_programming_language/ast.json
@@ -0,0 +1,79 @@
+[
+    {
+        "type": "VariableDeclaration",
+        "identifier": "buff",
+        "value": {
+            "type": "Number",
+            "value": 0
+        },
+        "vtype": "int",
+        "length": 4
+    },
+    {
+        "type": "VariableDeclaration",
+        "identifier": "counter",
+        "value": {
+            "type": "Number",
+            "value": 0
+        },
+        "vtype": "int",
+        "length": 1
+    },
+    {
+        "type": "FunctionDeclaration",
+        "name": "_start",
+        "body": [
+            {
+                "type": "While",
+                "condition": {
+                    "type": "BinaryExpression",
+                    "operator": "<",
+                    "left": {
+                        "type": "Identifier",
+                        "name": "counter"
+                    },
+                    "right": {
+                        "type": "Number",
+                        "value": 4
+                    }
+                },
+                "branch": [
+                    {
+                        "type": "Assignment",
+                        "identifier": {
+                            "type": "Identifier",
+                            "name": "buff",
+                            "offset": {
+                                "type": "Identifier",
+                                "name": "counter"
+                            }
+                        },
+                        "value": {
+                            "type": "Identifier",
+                            "name": "counter"
+                        }
+                    },
+                    {
+                        "type": "Assignment",
+                        "identifier": {
+                            "type": "Identifier",
+                            "name": "counter"
+                        },
+                        "value": {
+                            "type": "BinaryExpression",
+                            "operator": "+",
+                            "left": {
+                                "type": "Identifier",
+                                "name": "counter"
+                            },
+                            "right": {
+                                "type": "Number",
+                                "value": 1
+                            }
+                        }
+                    }
+                ]
+            }
+        ]
+    }
+]
\ No newline at end of file
diff --git a/the_e_programming_language/ast.ts b/the_e_programming_language/ast.ts
new file mode 100644
index 0000000..80210d8
--- /dev/null
+++ b/the_e_programming_language/ast.ts
@@ -0,0 +1,357 @@
+import { Token, TokenType } from "./tokenizer.ts";
+
+export interface ASTNode {
+    type: string;
+}
+
+export interface VariableDeclarationNode extends ASTNode {
+    type: "VariableDeclaration";
+    identifier: string;
+    value: ASTNode;
+    vtype: string;
+    length: number;
+}
+
+export interface FunctionDeclarationNode extends ASTNode {
+    type: "FunctionDeclaration";
+    name: string;
+    // params: string[];
+    body: ASTNode[];
+}
+
+export interface AssignmentNode extends ASTNode {
+    type: "Assignment";
+    identifier: IdentifierNode;
+    value: ASTNode;
+}
+
+export interface BinaryExpressionNode extends ASTNode {
+    type: "BinaryExpression";
+    operator: string;
+    left: ASTNode;
+    right: ASTNode;
+}
+
+export interface LiteralNode extends ASTNode {
+    type: "Literal";
+    value: string;
+}
+
+export interface NumberNode extends ASTNode {
+    type: "Number";
+    value: number;
+}
+
+export interface IdentifierNode extends ASTNode {
+    type: "Identifier";
+    name: string;
+    offset?: ASTNode;
+}
+
+export interface FunctionCallNode extends ASTNode {
+    type: "FunctionCall";
+    identifier: string;
+    args: ASTNode[];
+}
+
+// export interface BranchFunctionCallNode extends ASTNode {
+//     type: "BranchFunctionCall";
+//     identifier: string;
+//     args: ASTNode[];
+//     branches: ASTNode[][];
+// }
+
+// export interface StartBlockNode extends ASTNode {
+//     type: "StartBlock";
+//     body: ASTNode[];
+// }
+
+export interface IfNode extends ASTNode {
+    type: "If";
+    condition: ASTNode;
+    thenBranch: ASTNode[];
+    elseBranch?: ASTNode[];
+}
+
+export interface WhileNode extends ASTNode {
+    type: "While";
+    condition: ASTNode;
+    branch: ASTNode[];
+}
+
+// export interface ForNode extends ASTNode {
+//     type: "For";
+//     times: ASTNode;
+//     varname: ASTNode;
+//     branch: ASTNode[];
+// }
+
+// export interface GreenFlagNode extends ASTNode {
+//     type: "GreenFlag";
+//     branch: ASTNode[];
+// }
+
+// use 1 or 0 for boolean
+// export interface BooleanNode extends ASTNode {
+//     type: "Boolean";
+//     value: boolean;
+// }
+
+// export interface IncludeNode extends ASTNode {
+//     type: "Include";
+//     itype: string;
+//     path: string;
+// }
+
+// export interface ListDeclarationNode extends ASTNode {
+//     type: "ListDeclaration";
+//     identifier: string;
+//     value: ASTNode[];
+//     vtype: 'list' | 'global'
+// }
+
+export default class AST {
+    private tokens: Token[];
+    position: number = 0;
+
+    constructor(tokens: Token[]) {
+        this.tokens = tokens;
+    }
+
+    private peek(ahead = 0): Token {
+        return this.tokens[this.position + ahead];
+    }
+
+    private advance(): Token {
+        return this.tokens[this.position++];
+    }
+
+    private match(...types: TokenType[]): boolean {
+        if (types.includes(this.peek().type)) {
+            this.advance();
+            return true;
+        }
+        return false;
+    }
+
+    private matchTk(types: TokenType[], token = this.peek()): boolean {
+        if (types.includes(token.type)) {
+            return true;
+        }
+        return false;
+    }
+
+    private expect(type: TokenType, errorMessage: string): Token {
+        if (this.peek().type === type) {
+            return this.advance();
+        }
+        console.error('trace: tokens', this.tokens, '\nIDX:', this.position);
+        throw new Error(errorMessage);
+    }
+
+    parse(): ASTNode[] {
+        const nodes: ASTNode[] = [];
+        while (this.peek().type !== TokenType.EOF) {
+            nodes.push(this.parseStatement());
+        }
+        return nodes;
+    }
+
+    private parseStatement(): ASTNode {
+        if (this.matchTk([TokenType.TYPE])) {
+            const type = this.advance().value
+            let len = 1;
+            if (this.match(TokenType.LBRACKET)) {
+                len = Number(this.expect(TokenType.NUMBER, 'expected number after [').value);
+                this.expect(TokenType.RBRACKET, 'expected ] after length')
+            }
+            const identifier = this.expect(TokenType.IDENTIFIER, "expected var name after type (hint: functions dont have return types yet").value;
+            this.expect(TokenType.ASSIGN, "expected = after var name");
+            const value = this.parseAssignment(false);
+            return { type: "VariableDeclaration", identifier, value, vtype: type, length: len } as VariableDeclarationNode;
+        }
+
+        if (this.match(TokenType.FN_DECL)) {
+            const name = this.expect(TokenType.IDENTIFIER, "expected function name after fn").value;
+            // this.expect(TokenType.LPAREN, "Expected '(' after function name");
+            // const params: string[] = [];
+            // if (!this.match(TokenType.RPAREN)) {
+            //     do {
+            //         params.push(this.expect(TokenType.IDENTIFIER, "Expected parameter name").value);
+            //     } while (this.match(TokenType.COMMA));
+            //     this.expect(TokenType.RPAREN, "Expected ')' after parameters");
+            // }
+            this.expect(TokenType.LBRACE, "expected '{' before function body");
+            const body = this.parseBlock();
+            return { type: "FunctionDeclaration", name, body } as FunctionDeclarationNode;
+        }
+
+        if (this.match(TokenType.IF)) {
+            this.expect(TokenType.LPAREN, "Expected '(' after 'if'");
+            const condition = this.parseAssignment();
+            this.expect(TokenType.RPAREN, "Expected ')' after if condition");
+            this.expect(TokenType.LBRACE, "Expected '{' after if condition");
+            const thenBranch = this.parseBlock();
+            let elseBranch: ASTNode[] | undefined;
+            if (this.match(TokenType.ELSE)) {
+                this.expect(TokenType.LBRACE, "Expected '{' after 'else'");
+                elseBranch = this.parseBlock();
+            }
+            return { type: "If", condition, thenBranch, elseBranch } as IfNode;
+        }
+
+        if (this.match(TokenType.WHILE)) {
+            this.expect(TokenType.LPAREN, "Expected '(' after 'while'");
+            const condition = this.parseAssignment();
+            this.expect(TokenType.RPAREN, "Expected ')' after while condition");
+            this.expect(TokenType.LBRACE, "Expected '{' after while condition");
+            const branch = this.parseBlock();
+            return { type: "While", condition, branch } as WhileNode;
+        }
+
+        // if (this.match(TokenType.FOR)) {
+        //     this.expect(TokenType.LPAREN, "Expected '(' after 'for'");
+        //     const varname = this.parseAssignment();
+        //     const of = this.expect(TokenType.IDENTIFIER, 'expected of');
+        //     if (of.value !== 'of') throw new Error('expected of');
+        //     const times = this.parseAssignment();
+        //     this.expect(TokenType.RPAREN, "Expected ')' after for");
+        //     this.expect(TokenType.LBRACE, "Expected '{' after for");
+        //     const branch = this.parseBlock();
+
+        //     return { type: "For", varname, times, branch } as ForNode;
+        // }
+
+        // if (this.match(TokenType.GREENFLAG)) {
+        //     this.expect(TokenType.LBRACE, "Expected '{' after greenflag");
+        //     const branch = this.parseBlock();
+
+        //     return { type: "GreenFlag", branch } as GreenFlagNode;
+        // }
+
+        return this.parseAssignment();
+    }
+
+    private parseBlock(): ASTNode[] {
+        const nodes: ASTNode[] = [];
+
+        while (!this.match(TokenType.RBRACE)) {
+            nodes.push(this.parseStatement());
+        }
+
+        return nodes;
+    }
+
+    private parseAssignment(allowStuff = true): ASTNode {
+
+        const expr = this.parseBinaryExpression(allowStuff);
+        if (this.match(TokenType.ASSIGN)) {
+            if (expr.type !== "Identifier")
+                throw new Error("invalid assignment target; expected an identifier");
+            const value = allowStuff ? this.parseAssignment() : this.parsePrimary(false);
+            // let offset = undefined;
+            // if (this.match(TokenType.LBRACKET)) {
+            //     offset = this.parseAssignment();
+            //     this.expect(TokenType.RBRACKET, 'expected ]')
+            // }
+            return { type: "Assignment", identifier: (expr as IdentifierNode), value } as AssignmentNode;
+        }
+        return expr;
+    }
+
+    private parseBinaryExpression(allowStuff = false): ASTNode {
+        let left = this.parseCall(allowStuff);
+
+        while (this.peek().type === TokenType.BINOP) {
+            const operator = this.advance().value;
+            const right = this.parseCall();
+            left = { type: "BinaryExpression", operator, left, right } as BinaryExpressionNode;
+        }
+        return left;
+    }
+
+    private parseCall(allowStuff = false): ASTNode {
+        let expr = this.parsePrimary(allowStuff);
+
+        while (this.peek().type === TokenType.LPAREN) {
+            expr = this.finishCall(expr);
+        }
+        return expr;
+    }
+
+    private finishCall(callee: ASTNode): ASTNode {
+        this.expect(TokenType.LPAREN, "Expected '(' after function name");
+        //TODO - arguments
+        // const args: ASTNode[] = [];
+        // if (this.peek().type !== TokenType.RPAREN) {
+        //     do {
+        //         args.push(this.parseAssignment());
+        //     } while (this.match(TokenType.COMMA));
+        // }
+        this.expect(TokenType.RPAREN, "Expected ')' after arguments");
+
+
+        // if (this.peek().type === TokenType.LBRACE) {
+        //     const branches: ASTNode[][] = [];
+        //     do {
+        //         this.expect(TokenType.LBRACE, "Expected '{' for branch block");
+        //         branches.push(this.parseBlock());
+        //     } while (this.peek().type === TokenType.LBRACE);
+
+        //     if (callee.type !== "Identifier")
+        //         throw new Error("Branch function call expects an identifier");
+        //     return {
+        //         type: "BranchFunctionCall",
+        //         identifier: (callee as IdentifierNode).name,
+        //         args,
+        //         branches,
+        //     } as BranchFunctionCallNode;
+        // }
+
+
+        if (callee.type !== "Identifier")
+            throw new Error("Function call expects an identifier");
+        return {
+            type: "FunctionCall",
+            identifier: (callee as IdentifierNode).name,
+            // args,
+        } as FunctionCallNode;
+    }
+
+    private parsePrimary(allowOther = true): ASTNode {
+        const token = this.peek();
+
+        if (this.match(TokenType.NUMBER)) {
+            return { type: "Number", value: Number(token.value) } as NumberNode;
+        }
+
+        if (this.match(TokenType.LITERAL)) {
+            return { type: "Literal", value: token.value } as LiteralNode;
+        }
+
+        if (this.match(TokenType.IDENTIFIER) && allowOther) {
+
+            // if (["True", "true", "False", "false"].includes(token.value)) {
+            //     return {
+            //         type: "Boolean",
+            //         value: token.value === "True" || token.value === "true"
+            //     } as BooleanNode;
+            // }
+            let offset = undefined;
+            if (this.match(TokenType.LBRACKET)) {
+                offset = this.parseAssignment();
+                this.expect(TokenType.RBRACKET, 'expected ]')
+            }
+            return { type: "Identifier", name: token.value, offset } as IdentifierNode;
+        }
+
+        if (this.match(TokenType.LPAREN) && allowOther) {
+            const expr = this.parseAssignment();
+            this.expect(TokenType.RPAREN, "Expected ')' after expression");
+            return expr;
+        }
+
+        throw new Error(`Unexpected token: ${token.type}`);
+    }
+
+}
\ No newline at end of file
diff --git a/the_e_programming_language/code.txt b/the_e_programming_language/code.txt
new file mode 100644
index 0000000..f45a592
--- /dev/null
+++ b/the_e_programming_language/code.txt
@@ -0,0 +1,11 @@
+mov 97,0
+mov 98,0
+str 98,97
+mov 97,0
+mov 98,4
+str 98,97
+pop 97
+mov 98,0
+cmp 97,98
+mov 97,18
+jnz 97
\ No newline at end of file
diff --git a/the_e_programming_language/compiler.ts b/the_e_programming_language/compiler.ts
new file mode 100644
index 0000000..37538f7
--- /dev/null
+++ b/the_e_programming_language/compiler.ts
@@ -0,0 +1,151 @@
+import { ASTNode, BinaryExpressionNode, FunctionDeclarationNode, NumberNode, VariableDeclarationNode, WhileNode } from "./ast.ts";
+// import { PC } from "../pc.ts";
+// const pc = new PC();
+
+type Opcode = 
+    'mov'  |
+    'swp'  |
+    'ld'   |
+    'str'  |
+    'add'  |
+    'sub'  |
+    'mul'  |
+    'div'  |
+    'mod'  |
+    'shl'  |
+    'shr'  |
+    'cmp'  |
+    'cmr'  |
+    'and'  |
+    'or'   |
+    'xor'  |
+    'not'  |
+    'push' |
+    'pop'  |
+    'halt' |
+    'sys'  |
+    'jmp'  |
+    'jnz'  |
+    'jz'   |
+    'jmr'  |
+    'ret'  |
+    'end';
+type Register = 97 | 98 | 99 | 100
+
+interface Instruction {
+    opcode: Opcode,
+    args: (Register | number)[]
+}
+
+const types: Record<string, number> = {
+    'int' : 1,
+    'bool': 1,
+    'char': 1
+}
+
+const A: Register = 97;
+const B: Register = 98;
+// deno-lint-ignore no-unused-vars
+const C: Register = 99;
+// deno-lint-ignore no-unused-vars
+const D: Register = 100;
+
+export default class Compiler {
+    vars: Record<string, [number, number]> = {};
+    functions: Record<string, number> = {};
+    AST: ASTNode[];
+    lastAddr: number = 0;
+    instructions: Instruction[] = [];
+    constructor (ast: ASTNode[]) {
+        this.AST = ast
+    }
+    compile (node: ASTNode) {
+        if ((node as VariableDeclarationNode).type == 'VariableDeclaration') {
+            const varDeclNode = node as VariableDeclarationNode;
+            if (!types[varDeclNode.vtype]) throw 'unknown type';
+            const addr = this.vars[varDeclNode.identifier] =
+                [this.lastAddr, types[varDeclNode.vtype] * varDeclNode.length];
+            this.lastAddr += types[varDeclNode.vtype] * varDeclNode.length;
+            if (varDeclNode.value.type != 'Number') throw 'a';
+            this.instructions.push({
+                opcode: 'mov',
+                args: [A, (varDeclNode.value as NumberNode).value]
+            })
+            this.instructions.push({
+                opcode: 'mov',
+                args: [B, addr[0]]
+            })
+            this.instructions.push({
+                opcode: 'str',
+                args: [B, A]
+            })
+        } else if ((node as FunctionDeclarationNode).type == 'FunctionDeclaration') {
+            const fnDeclNode = node as FunctionDeclarationNode;
+            this.functions[fnDeclNode.name] = this.instructions
+                .map(k => 1 + k.args.length)
+                .reduce((prev, curr) => {
+                    return prev + curr 
+                }, 0);
+            for (const node of fnDeclNode.body) {
+                this.compile(node)
+            }
+        } else if ((node as BinaryExpressionNode).type == 'BinaryExpression') {
+            const binExpNode = node as BinaryExpressionNode;
+            this.instructions.push({
+                opcode: 'pop',
+                args: [A]
+            })
+            this.instructions.push({
+                opcode: 'pop',
+                args: [B]
+            })
+            switch (binExpNode.operator) {
+                case '+':
+                    this.instructions.push({
+                        opcode: 'add',
+                        args: [A, A, B]
+                    })
+                    break;
+            
+                default:
+                    throw 'oh no'
+            }
+            this.instructions.push({
+                opcode: 'push',
+                args: [A]
+            })
+        } else if ((node as WhileNode).type == 'While') {
+            const whileNode = node as WhileNode;
+            const start = this.instructions
+                .map(k => 1 + k.args.length)
+                .reduce((prev, curr) => {
+                    return prev + curr 
+                }, 0);
+            for (const node of whileNode.branch) {
+                this.compile(node)
+            }
+            this.instructions.push({
+                opcode: 'pop',
+                args: [A]
+            })
+            this.instructions.push({
+                opcode: 'mov',
+                args: [B, 0]
+            })
+            this.instructions.push({
+                opcode: 'cmp',
+                args: [A, B]
+            })
+            this.instructions.push({
+                opcode: 'mov',
+                args: [A, start]
+            })
+            this.instructions.push({
+                opcode: 'jnz',
+                args: [A]
+            })
+        } else {
+            console.error(`!!! UNIMPLEMENTED NODE `, node.type, node)
+        }
+    }
+}
\ No newline at end of file
diff --git a/the_e_programming_language/lang.ts b/the_e_programming_language/lang.ts
new file mode 100755
index 0000000..5c00b98
--- /dev/null
+++ b/the_e_programming_language/lang.ts
@@ -0,0 +1,31 @@
+import Tokenizer from "./tokenizer.ts";
+import ASTGen from "./ast.ts";
+import Compiler from "./compiler.ts";
+const input = Deno.readTextFileSync('test.e')
+
+const tokenizer = new Tokenizer(input);
+const tokens = tokenizer.tokenize();
+
+console.log(tokens)
+
+const astGenerator = new ASTGen(tokens);
+
+let ast;
+try {
+    ast = astGenerator.parse()
+} catch (error) {
+    console.error(error);
+    console.log('at', astGenerator.position, tokens.map((a, i) => i == astGenerator.position ? `${a.type}(${a.value}) <--` : `${a.type}(${a.value})`).join('\n'))
+    Deno.exit(1)
+}
+
+console.log(ast)
+
+const compiler = new Compiler(ast);
+
+for (const node of compiler.AST) {
+    compiler.compile(node)
+}
+
+Deno.writeTextFileSync('ast.json', JSON.stringify(ast, null, 4))
+Deno.writeTextFileSync('code.txt', compiler.instructions.map(i => `${i.opcode}${i.args.length > 0 ? ' ' : ''}${i.args.join(',')}`).join('\n'))
\ No newline at end of file
diff --git a/the_e_programming_language/test-2.e b/the_e_programming_language/test-2.e
new file mode 100755
index 0000000..3b1b371
--- /dev/null
+++ b/the_e_programming_language/test-2.e
@@ -0,0 +1,6 @@
+int[8] a = 0
+int test = 5
+fn _start {
+a[4] = 5
+a[test] = 6
+}
\ No newline at end of file
diff --git a/the_e_programming_language/test.e b/the_e_programming_language/test.e
new file mode 100755
index 0000000..4996d5c
--- /dev/null
+++ b/the_e_programming_language/test.e
@@ -0,0 +1,43 @@
+// comments exist
+// 
+// types (in addresses (they store 2 bytes if you forgot)):
+// int - 1
+// char - 1
+// bool - 1
+// uuh yeah,, theyre all 1 address ;-;
+//
+// $VARNAME is the address of the var, when used in mov it means that we get that var
+// [$VARNAME] is the address of the var, but when it's used in mov it means we set to the address
+
+// translates to:
+// mov a 0
+// mov $counter a
+// prob not gonna make it do assembly tho
+int[4] buff = 0
+int counter = 0
+
+fn _start {
+    // translates to
+    // <inner code>
+    // mov a $counter
+    // mov b 4
+    // cmp a b
+    // jz $start_of_inner_code
+    while (counter < 4) {
+        // translates to
+        // mov a [$buff]
+        // mov b [$counter]
+        // add a a b
+        // mov b $counter
+        // str a b
+        buff[counter] = counter
+        // translates to
+        // mov a $counter ; further translates to:
+        //                ; mov a $counter
+        //                ; ld a a
+        // mov b 1
+        // add a a b
+        // str $counter a
+        counter = counter + 1
+    }
+}
\ No newline at end of file
diff --git a/the_e_programming_language/test.e.txt b/the_e_programming_language/test.e.txt
new file mode 100755
index 0000000..c8d09c5
--- /dev/null
+++ b/the_e_programming_language/test.e.txt
@@ -0,0 +1,43 @@
+// comments exist
+// 
+// types (in addresses (they store 2 bytes if you forgot)):
+// int - 1
+// char - 1
+// bool - 1
+// uuh yeah,, theyre all 1 address ;-;
+//
+// $VARNAME is the address of the var, when used in mov it means that we get that var
+// [$VARNAME] is the address of the var, but when it's used in mov it means we set to the address
+
+// translates to:
+// mov a 0
+// mov $counter a
+// prob not gonna make it do assembly tho
+int counter = 0
+int[4] buff = 0
+
+fn _start {
+    // translates to
+    // <inner code>
+    // mov a $counter
+    // mov b 4
+    // cmp a b
+    // jz $start_of_inner_code
+    while (counter < 4) {
+        // translates to
+        // mov a [$buff]
+        // mov b [$counter]
+        // add a a b
+        // mov b $counter
+        // str a b
+        buff[counter] = counter
+        // translates to
+        // mov a $counter ; further translates to:
+        //                ; mov a $counter
+        //                ; ld a a
+        // mov b 1
+        // add a a b
+        // str $counter a
+        counter = counter + 1
+    }
+}
\ No newline at end of file
diff --git a/the_e_programming_language/tokenizer.ts b/the_e_programming_language/tokenizer.ts
new file mode 100755
index 0000000..57d0131
--- /dev/null
+++ b/the_e_programming_language/tokenizer.ts
@@ -0,0 +1,171 @@
+export enum TokenType {
+    TYPE       = "TYPE",
+    FN_DECL    = "FN_DECL",
+    LITERAL    = "LITERAL",
+    NUMBER     = "NUMBER",
+    LPAREN     = "LPAREN",
+    RPAREN     = "RPAREN",
+    LBRACE     = "LBRACE",
+    RBRACE     = "RBRACE",
+    LBRACKET   = "LBRACKER",
+    RBRACKET   = "RBRACKER",
+    COMMA      = "COMMA",
+    WHILE      = "WHILE",
+    IF         = "IF",
+    ELSE       = "ELSE",
+    ASSIGN     = "ASSIGN",
+    BINOP      = "BINOP",
+    IDENTIFIER = "IDENTIFIER",
+
+    EOF        = "EOF",
+}
+
+export interface Token {
+    type: TokenType;
+    value: string;
+}
+
+const types = ['int', 'bool', 'char']
+
+// i hardly know her
+export default class Tokenizer {
+    private source: string;
+    private position: number = 0;
+
+    constructor(source: string) {
+        this.source = source;
+    }
+
+    private isAlpha(char: string): boolean {
+        return /[a-zA-Z_#]/.test(char);
+    }
+
+    private isDigit(char: string): boolean {
+        return /-?[\d\.]/.test(char);
+    }
+
+    private isWhitespace(char: string): boolean {
+        return /\s/.test(char);
+    }
+
+    private advance(): string {
+        return this.source[this.position++];
+    }
+
+    private peek(): string {
+        return this.source[this.position] || "";
+    }
+
+    private match(expected: string): boolean {
+        if (this.peek() === expected) {
+            this.position++;
+            return true;
+        }
+        return false;
+    }
+
+    tokenize(): Token[] {
+        const tokens: Token[] = [];
+
+        let inComment = false;
+        let global = 0;
+
+        while (this.position < this.source.length) {
+            const char = this.advance();
+
+            if (global > 0) global--;
+
+            if (inComment) {
+                if (char == '\n') inComment = false;
+                continue;
+            } else if (char == '/' && this.peek() == '/') {
+                inComment = true
+            } else if (this.isWhitespace(char)) {
+                continue;
+            } else if (this.isAlpha(char)) {
+                let identifier = char;
+                while (this.isAlpha(this.peek()) || this.isDigit(this.peek())) {
+                    identifier += this.advance();
+                }
+
+                // if (identifier === "#include") {
+                //     // while(this.isWhitespace(this.peek()) && this.position < this.source.length) {
+                //     //     this.advance()
+                //     // }
+                //     // if (this.advance() != '<') throw "Expected a < after #include"
+                //     // let id = ''
+                //     // while (this.peek() != '>'
+                //     //     && (this.isAlpha(this.peek()) || this.isDigit(this.peek()))) {
+                //     //     id += this.advance();
+                //     // }
+                //     // if (this.advance() != '>') throw "Expected a > after #include <..."
+                //     tokens.push({ type: TokenType.INCLUDE, value: identifier });
+                // } else if (identifier === "var") tokens.push({ type: TokenType.VAR, value: global > 0 ? 'global' : identifier });
+                // else if (identifier === "list") tokens.push({ type: TokenType.LIST, value: global > 0 ? 'global' : identifier });
+                // else if (identifier === "global") global = 2;
+                if (identifier === "fn") tokens.push({ type: TokenType.FN_DECL, value: identifier });
+                else if (identifier === "if") tokens.push({ type: TokenType.IF, value: identifier });
+                else if (identifier === "else") tokens.push({ type: TokenType.ELSE, value: identifier });
+                else if (identifier === "while") tokens.push({ type: TokenType.WHILE, value: identifier });
+                else if (types.includes(identifier)) tokens.push({ type: TokenType.TYPE, value: identifier });
+                // else if (identifier === "for") tokens.push({ type: TokenType.FOR, value: identifier });
+                else tokens.push({ type: TokenType.IDENTIFIER, value: identifier });
+            } else if (this.isDigit(char)) {
+                let number = char;
+                while (this.isDigit(this.peek())) {
+                    number += this.advance();
+                }
+                tokens.push({ type: TokenType.NUMBER, value: number });
+            } else if (char === '"') {
+                let string = "";
+                while (this.peek() !== '"' && this.peek() !== "") {
+                    string += this.advance();
+                }
+                if (!this.match('"')) {
+                    throw new Error("Unterminated string");
+                }
+                tokens.push({ type: TokenType.LITERAL, value: string });
+            } else if (char === "(") tokens.push({ type: TokenType.LPAREN, value: char });
+            else if (char === ")") tokens.push({ type: TokenType.RPAREN, value: char });
+            else if (char === "{") tokens.push({ type: TokenType.LBRACE, value: char });
+            else if (char === "}") tokens.push({ type: TokenType.RBRACE, value: char });
+            else if (char === "[") tokens.push({ type: TokenType.LBRACKET, value: char });
+            else if (char === "]") tokens.push({ type: TokenType.RBRACKET, value: char });
+            else if (char === ",") tokens.push({ type: TokenType.COMMA, value: char });
+            else if (char === "+") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "-") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "*") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "/") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "%") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "=" && this.peek() === '=') {
+                tokens.push({ type: TokenType.BINOP, value: char });
+                this.advance();
+            }
+            else if (char === "&" && this.peek() === '&') {
+                tokens.push({ type: TokenType.BINOP, value: char });
+                this.advance();
+            }
+            else if (char === "!" && this.peek() === '=') {
+                tokens.push({ type: TokenType.BINOP, value: '!=' });
+                this.advance();
+            }
+            else if (char === "<" && this.peek() === '=') {
+                tokens.push({ type: TokenType.BINOP, value: '<=' });
+                this.advance();
+            }
+            else if (char === ">" && this.peek() === '=') {
+                tokens.push({ type: TokenType.BINOP, value: '>=' });
+                this.advance();
+            }
+            else if (char === ">") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "<") tokens.push({ type: TokenType.BINOP, value: char });
+            else if (char === "=") tokens.push({ type: TokenType.ASSIGN, value: char });
+            else {
+                throw new Error(`Unexpected character: ${char}`);
+            }
+        }
+
+        tokens.push({ type: TokenType.EOF, value: "" });
+        return tokens;
+    }
+}
\ No newline at end of file