- 
      
- 
        Save Killaship/927951649bbf2f2399565c5f4b47c621 to your computer and use it in GitHub Desktop. 
| /* | |
| Killaship | |
| 2022 | |
| November 13th, ~10:30 PM EST | |
| This took like an hour or two to make, WITH a tutorial and previous experience! | |
| A VM following the specifications of the 'mac' architecture, as outlined in this blog: | |
| https://felix.engineer/blogs/virtual-machine-in-c/ | |
| I was pretty tired while writing this, so the code might suck. | |
| Hell, I typed & instead of % twice and was wondering for minutes about it! | |
| I started work on this at ~ 9:15, I recorded the progress. | |
| Notes: | |
| - In loops, stack overflows only happen if your program is "unbalanced," | |
| i.e., end up pushing more than there's space for. If a program is balanced, it'll run forever. | |
| It might be hard to get a ^C in, so beware. | |
| - There's a very limited instruction set, either add to it on your own, | |
| or wait for me to, if I ever do. You'd be better off following the original creator of mac, | |
| found at this Github link: https://github.com/felixangell/mac | |
| I only did the bare minimum to make what's outlined in the blog work. | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdbool.h> | |
| #include <string.h> | |
| int ip = 0; | |
| int sp = -1; | |
| bool run = true; | |
| typedef enum { // this gives us reference names for the opcodes. | |
| PSH, | |
| ADD, | |
| POP, | |
| SET, | |
| STKRESET, | |
| JMP, | |
| HLT | |
| } ISA; | |
| typedef enum { | |
| A, B, C, D, E, F, SP, IP, // I spent longer trying to copy paste this than to actually type it :/ | |
| NUM_OF_REGISTERS | |
| } REG; | |
| int registers[NUM_OF_REGISTERS]; // what's funny is that you can use the NUM_OF_REGISTERS register as a register if you tried to in code | |
| #define sp (registers[SP]) | |
| #define ip (registers[IP]) | |
| // ^^ quick lil' hack | |
| int program[] = { // unsigned char instead of int since we don't need billions of opcodes | |
| STKRESET, // wow, looks like we do need this. | |
| PSH, 5, // well, fuck it, I just realized we need to add or subtract large numbers | |
| PSH, 6, // I mean, we could go all harvard arch, but that would kinda suck ass | |
| ADD, | |
| POP, | |
| JMP, 0, | |
| HLT | |
| }; | |
| int stack[256]; // stack array | |
| int fetch() { | |
| return program[ip]; // FFS, this doesn't need a function | |
| } | |
| void eval(int instr) { | |
| // what kind of crack was that guy's compiler smoking? | |
| // maybe it was llvm | |
| int a = 69; // debug values | |
| int b = 69; | |
| int result = 69; | |
| int val_popped = 69; | |
| int pushval = 69; | |
| switch(instr) { | |
| case POP: | |
| val_popped = stack[sp--]; // MAKE SURE THE INC/DEC IS ON THE RIGHT GODDAMN SIDE | |
| printf("popped %d!\n", val_popped); | |
| break; | |
| case ADD: | |
| a = stack[sp--]; | |
| printf("a is %d!\n", a); // I really would be better off using GDB but who cares | |
| b = stack[sp--]; | |
| printf("b is %d!\n", b); // I really would be better off using GDB but who cares | |
| result = b + a; | |
| printf("a plus b is %d!\n", result); // I really would be better off using GDB but who cares | |
| sp++; // increment stack pointer **before** | |
| stack[sp] = result; // set the value to the top of the stack | |
| printf("I just pushed %d!\n", stack[sp]); | |
| break; | |
| case PSH: | |
| sp++; | |
| stack[sp] = program[++ip]; | |
| pushval = stack[sp]; | |
| printf("pushed %d!\n", pushval); // grammar laws request that the comma is included inside the quotation mark | |
| stack[sp] = pushval; // this uses something I didn't know about before I first read the blog | |
| break; // it uses the ++ lvalue to increment the ip at the same time as reading it | |
| case SET: // nevermind | |
| registers[program[ip++]] = registers[program[ip++]]; // zoo wee mama this is weird | |
| // it increments the IP and then in the same line increments it again | |
| break; | |
| case STKRESET: // stack reset | |
| memset(&stack, 0, 256); // should really unhardcode this later | |
| sp = -1; | |
| break; | |
| case JMP: | |
| printf("before: %d. ", ip); // I should get sleep, I mistyped something really obvious | |
| ip = program[++ip]; // brain farted here | |
| printf("after %d.\n", ip); | |
| break; | |
| case HLT: | |
| run = false; | |
| break; | |
| } | |
| } | |
| int main() { | |
| int instr = program[ip]; | |
| while(run == true) { | |
| instr = fetch(); | |
| eval(instr); | |
| ip++; | |
| } | |
| printf("done!\n"); | |
| return 0; | |
| } | 
src/main.c 2008 gcc src/main.c
2009 ./a.out
2010 gcc src/main.c
2011 ./a.out
2012 gcc src/main.c
2013 ./a.out
2014 # jesus fucking christ what am I missing
2015 # does 5 + 6 really equal 0
2016 # is my whole life a lie
2017 gcc src/main.c
2018 ./a.out
2019 gcc src/main.c
2020 # no, my life isn't a lie
2021 # -- was on the wrong side
2022 ./a.out
2023 gcc src/main.c
2024 ./a.out
2025 # whoops, didn't need it at all
2026 # I was probably reading from un alloc'd memory
2027 gcc src/main.c
2028 ./a.out
2029 gcc src/main.c
2030 ./a.out
2031 gcc src/main.c
2032 ./a.out
2033 gcc src/main.c
2034 ./a.out
2035 gcc src/main.c
2036 ./a.out
2037 gcc src/main.c
2038 ./a.out
2039 gcc src/main.c
2040 ./a.out
2041 gcc src/main.c
2042 ./a.out
2043 # dafuq
2044 ./a.out
2045 gcc src/main.c
2046 ./a.out
2047 # there we go
2048 gcc src/main.c
2049 ./a.out
2050 gcc src/main.c
2051 ./a.out
2052 gcc src/main.c
2053 ./a.out
2054 # BWAHAHAHA
2055 gcc src/main.c
2056 ./a.out
2057 ## jesus christ what have I done
2058 gcc src/main.c
2059 ## jesus christ what have I done
2060 ./a.out
2061 gcc src/main.c
2062 ./a.out
2063 gcc src/main.c
2064 ./a.out
2065 # there, it works
2066 # I accidentally turned on airplane mode
2067 # this keyboard does NOT need that button
2068 # fuck laptops that have weird buttons
2069 gcc src/main.c
2070 ./a.out
2071 gcc src/main.c
2072 ./a.out
2073 micro ~/.bashhistory
2074 history
or my bash history, I guess
hi
check the comments for me slowly going insane