Welcome to the world of my very own tiny virtual CPU!
This project consists of 3 parts: an assembler, a disassembler and a processor. Each part has its own executable, but really they are meant to be used together.
The assembler program reads a text file written in a custom assembly language and compiles it to a binary (compiled.jf by default) that can be then read by the CPU for execution.
Currently the following assembler commands are supported:
- hlt - Ends program execution
- ver - Verifies the integrity of the processor stack (only works if PROT_LEVEL > 0)
- dmp - Dumps the info about the processor stack into a log file (only works if PROT_LEVEL > 0)
- out - Pops a value off the stack and prints it to standard output
- in - Reads a number from standard input and pushed it onto the stack
- push 1 - Pushes 1 (or any number) onto the stack
- push ax - Pushes value from the ax register onto the stack
- push [1], push [ax], push [ax + 1] - Push values from CPU RAM onto the stack, where the RAM address is the total number value in the brackets
- pop - Pops a value off the stack
- pop ax - Pops a value from the stack into the ax register
- pop [1], ... - Pops the value from the stack into RAM
- abs - Takes the absolute value of the top stack element, and pushes it onto the stack
- sqrt - Takes the square root of the top stack element, and pushes it onto the stack
- add - Pops 2 values off the stack, adds them, pushes them back onto the stack, right operand is the top stack value
- sub - Adds 2 top stack values
- mul - Multiplies 2 top stack values
- div - Divides 2 top stack values
- jmp lbl - Jumps to label lbl
- ja lbl - Jumps to label lbl if the top stack values satisfy the inequality first > second
- jae lbl - Jumps if >=
- jb lbl - Jumps if <
- jbe lbl - Jumps if <=
- je lbl - Jumps if ==
- jne lbl - Jumps if !=
- call func - Jumps to a function with label func, the function must have a ret in the end
- draw - Draws lines of specified width from VRAM to standard output until \0 in is encountered
- ret - Returns to the function call site
Labels are specified in the following form:
jmp label
..
some
kode
..
label:
..
more
kode
..
The assembler ignores leading whitespaces and empty lines, so you can format your code to be more readable (just be careful not to add any extra spaces before and after command arguments or it won't compile)
You can find example .asm programs in the examples folder of the repo
The disassembler program reads a binary .jf file and decompiles it into the custom assembler program with using the command set described in the ASSembler section
The processor program takes in a compiled binary .jf file and executes the program from it. The processor version must match the command set version or the processor won't work.
The processor has a dynamic stack for handling numeric values, 8 registers ax - hx for storing values, a call stack that makes nested function calls possible and a 1 MB RAM (you can change its size by recompiling with a different RAM_SIZE value)
Unix based system or WSL(code written for Linux originally), git(kinda), gcc, make
You have to first compile the source code by using make in the root directory of the repo
git clone https://github.com/morgunovmi/processor && cd processor/
make && cd build/
Once you have written an assembler program you can compile it by running
./assembler program.asm
which will result in a compiled.jf binary file. You can also explicitly name the binary file with the -o flag
./assembler program.asm -o my_name_is.jf
By default this program also outputs a clean.asm file, that contains your code without extra whitespaces. And obviously your program file has to be in the same directory as the executable.
You can decompile a binary file by running
./disassembler compiled.jf
or
./disassembler compiled.jf -o bollocks.asm
You can run the compiled binary with the following command
./processor compiled.jf
Don't forget to play around with the ascii part of the examples. For full support you need ffmpeg and jp2a programs:
sudo apt update
sudo apt install jp2a
sudo apt install ffmpeg
You can use the a2asm program to turn your image into a .gasm program, current terminal dimensions are used for conversion
./a2asm img.jpeg
or explicitly
./a2asm -i img.jpeg
And finally, you can even convert your video into a .gasm program, so you can enjoy your favourite show in ascii form in your terminal(without sound for now):
./a2asm -v video.mp4
This program will output a .gasm program that you can then compile and run!