I made this game to teach my daughter how buffer overflows work. Looking at programs as something you can play with, and poke and twist and make it do something else, is my favorite part of modern computing. I think its the right way to look at programs. When your microwave oven gets an update and starts crashing, you can hack it. Or when your keyboard controller’s firmware is bad, you can hack it (looking at you vortex pok3r). She is 12 yo now but her assembler skills are getting better and better, hopefully one day she will be able to hack her own keyboard :)
The game is about creating a small shellcode in memory by copying existing instructions and then exploiting a buffer overflow to jump into it, so that you can overwrite your opponent’s return address to force them to go to the game_over() function.There are other mechanics as well and more layers of strategy (like setting the exception handler or monkeypatching).
All players share the same memory, and execute the same program, while time sharing the same processor running preemptive scheduling os, so each turn the player executes 10 instructions, after that the process is interrupted by the operating system, and its the other player's turn. Each player's stack pointer starts at a different location. There is no virtual memory.How it looks when we play the game:
The code is compiled with riscv64-unknown-elf-gcc -fomit-frame-pointer -fno-inline-small-functions -mno-shorten-memrefs -march=rv32g -mabi=ilp32 -ffreestanding -nostdlib -nostartfiles -T code/link.ld -O0 -fverbose-asm -g -o game game.c, the linker script link.ld has just offsets for the specific functions so the fit nicely on the board. The no optimization -O0 makes the machine code pretty verbose, but also straight forward. Then I use riscv64-unknown-elf-objdump -S -l -fd game, parse it and fix the ▲ and ✎ instructions, convert the jump offset from hex to dec and clean the assembly a bit, then match it with the source code and generate a svg which is then converted to a pdf with inkscape.
All jumps are relative to the current program counter, even if they appear as absolute addresses in the disassembler, so jal a4, 0 (machine code 1903) is actually an infinite loop when executed.
0.0.6: while(*prun) instead of while(run), this way the opponent could forcefully crash you by making you do unaligned dereference; change the NOP rule to be placable only in functions that are not being executed at the moment
We made few card games that you might find useful, the C game and the machine code game particularly helped with understanding assembly better.
Programming Time, which is a game to teach python and some more fundamental algorithms, from hash tables to RSA
The C Pointer Game - Pointers, Arrays and Strings, a game to teach kids to look at the computer memory and understand references and values
4917, a game to teach kids machine code and how the CPU works with memory and registers
The Unix Pipes Game, a game to teach kids to use basic UNIX commands:
cat, sort, grep, head, tail, wc, uniq
The Unix Pipes Game - Process Substitution, an expansion of the Unix Pipes Game to teach process substitution and also:
paste, tr, cut, bc
RunLength Encoding for Kids, small cards "game" to explain runlength encoding
PUNK0 - The Function Composition Card Game, use cards to manipulate a list and use its values to win the game
Programming for kids, a log of my journey of teaching my daughter how to code
The the squares on the left/right are ascii encoded binary message, you can try to decipher it, the white squares are 1, and black on black squares are 0, use the spacing to figure out where the 0's go.
The colors are minimal, so people can print it cheaply, and it is also clear on a3 and a4 black and white printers, the only colors used are red (255,0,0), blue(0,0,255), black (0,0,0) and white (255,255,255).
I am not a designer, but the current design is maybe 20th iteration or so, and it came out after listening to Ghost In The Shell's Making of a Cyborg for 5 hours.
The project logo symbolizes the overflow, and it is randomly generated, the current random seed made me feel a bit uneasy, so I left it like that.
Spacing on the logo and the Japanese text is a bit off, this is in order to be able to fold the A3 paper in half and not go through any text.
The Japanese text is from the last words of The Pirate King, Gol D. Roger: Inherited Will, The Destiny of the Age, and The Dreams of the People. As long as people continue to pursue the meaning of Freedom, these things will never cease to be!
No syntax highlighting. I dont use syntax highlighting, and also I dont teach my daughter to use it. I dont have strong preference, but it just forces me to think that certain things in code are more important than others (depending on the theme). Without highlighting I can do my own judgment, and can easily focus on what I think matters.
I would like to thank Peter, William, Shantanu, Rares and my daughter who played 50 different versions of the game, all of which were quite bad :) but they didnt give up. And thanks to tn1 who helped me a lot with the design, particularly telling me what is not good.
Also big thank you to the people working on the Terminus Font which is absolute beauty.
Special thanks to OpenMachine's tinyfive emulator which I used to test the game, until I wrote my own for the web version.
Thanks to gamesounds.xyz for the .wav files I got for the web version, and also Karl Casey @ White Bat Audio for the background music
And of course many thanks to the people working on RISC-V it is super fun to work with it.
Many thanks to @matsuu for pointing out a typo in the Japanese spelling.
If you have an idea about a different board or rules, or you find a bug in the board or the online version please send me an email, also turns out I can play this game with my daughter and like 2 people in my whole contact list , so if you have fun playing it I would love to hear about it.
You can find many RISC-V assembly guides such as: https://riscv-programming.org/ or riscv-asm-manual, and many interpreters like: cs3410 risc-v interpreter, or decoders like luplab's rvcodecjs which is a great instruction decoder e.g. enter 0x13 (the nop instruction) there and see how it decodes. If you are struggling you can also search youtube for 'risc v assembly tutorial' and there are many really good videos, sadly I am not sure which one will work for you, so don't get discouraged and just try few of them.
I made some exercises for my daughter, each day I printed few memory templates and few of the code examples below and she just executed the instructions, Some days I changed the code on the fly, or spent more time explaining casting and structures for example. But the basic RISC-V assembly she was able to understand pretty fast.
The hangman version is the same as the normal pdf, but few of the assembly instructions are missing and you have to fill them in:
If you need to step up your C game, we use Beej's C guide: Beej's Guide to C Programming, particularly the first 7-8 chapters. But there are many very good resources. You can also use the following assembly examples to brush up on your C, a good example is this pointer exercise:
When you print the exercise and the memory template it looks like this:
Those are the exercises we have done so far: