Skip to content

Instantly share code, notes, and snippets.

@Killaship
Created November 14, 2022 03:31
Show Gist options
  • Save Killaship/927951649bbf2f2399565c5f4b47c621 to your computer and use it in GitHub Desktop.
Save Killaship/927951649bbf2f2399565c5f4b47c621 to your computer and use it in GitHub Desktop.
mac-vm
/*
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;
}
@Killaship
Copy link
Author

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

@Killaship
Copy link
Author

hi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment