This document was written by me and GPT together.
This project is a 16-bit x86 real-mode bootloader written in assembly language that runs directly on IBM PC–compatible hardware. The program is loaded by the BIOS at boot time and executes without any operating system. It implements a minimal version of the classic Snake game using BIOS interrupts and direct memory manipulation for graphics rendering, keyboard input, timing control, and game logic.
Unlike applications running under DOS or modern operating systems, this program operates in a bare-metal environment, meaning:
When a PC boots:
0x7C00.CS:IP = 0000:7C00.0xAA55.The program begins with:
[org 0x7c00]
[bits 16]
org 0x7c00 tells the assembler the code will be loaded at address 0x7C00.bits 16 ensures 16-bit instruction encoding.The game uses VGA Mode 13h, which provides:
0xA000Initialization code:
start:
xor ax, ax
mov ds, ax
mov ax, 0x0013
int 0x10
mov ax, 0xa000
mov es, ax
xor ax, ax → Clear AX.mov ds, ax → Set data segment to 0.mov ax, 0x0013 / int 0x10 → BIOS interrupt to switch to Mode 13h.mov es, 0xA000 → ES points to VGA framebuffer.From this point onward, writing to [es:offset] directly modifies pixels on screen.
init_game:
xor di, di
mov cx, 32000
xor eax, eax
rep stosw
stosw writes 2 bytes.DI = 0ES = 0xA000rep stosw clears entire screen to color 0 (black)This is an efficient memory-clearing technique in 16-bit assembly.
The snake’s body is stored in conventional memory starting at address 0x8000.
mov word [0x8000], 32160
mov si, 0x8000
mov bx, 0x8000
mov bp, 1
| Register | Purpose |
|---|---|
SI |
Snake head pointer |
BX |
Snake tail pointer |
BP |
Direction increment |
[0x8000+] |
Snake body position list |
Each snake segment stores a linear framebuffer offset (0–63999).
Pixel address formula:
offset = y * 320 + x
Initial position 32160 corresponds to:
32160 / 320 = 100.5 → approx middle of screen
spawn_apple:
rdtsc
xor dx, dx
mov cx, 64000
div cx
mov di, dx
cmp byte [es:di], 0
jne spawn_apple
mov byte [es:di], 40
rdtsc reads CPU timestamp counter.DX) becomes a random pixel offset.0).40).Note: rdtsc requires a 586+ CPU.
game_loop:
mov ah, 0x86
mov cx, 0
mov dx, 0x4000
int 0x15
int 0x15, AH=0x86 provides a delay function.CX:DX specifies microsecond delay.mov ah, 0x01
int 0x16
jz update_pos
xor ah, ah
int 0x16
Direction control:
cmp al, 'w'
je move_up
cmp al, 's'
je move_down
cmp al, 'a'
je move_left
cmp al, 'd'
je move_right
Uses ASCII comparison for WASD control.
update_pos:
mov ax, [si]
add ax, bp
mov di, ax
[SI]BPcmp ax, 64000
jae game_over
Only checks upper boundary; edge wrapping and vertical boundary checks are incomplete.
cmp byte [es:di], 40
je eat_apple
cmp byte [es:di], 0
jne game_over
Cases:
| Pixel Value | Meaning |
|---|---|
| 0 | Empty |
| 2 | Snake body |
| 40 | Apple |
If pixel ≠ 0 and ≠ 40 → collision.
mov byte [es:di], 2
add si, 2
mov [si], di
mov di, [bx]
mov byte [es:di], 0
add bx, 2
Process:
Snake length remains constant.
eat_apple:
mov byte [es:di], 2
add si, 2
mov [si], di
jmp spawn_apple
Difference:
game_over:
jmp start
Game restarts by reinitializing environment.
No score tracking or message display due to boot sector size constraints.
times 510-($-$$) db 0
dw 0xaa55
0xAA55.Without this signature, BIOS will refuse to boot.
nasm -f bin boot.asm -o snake.img
qemu-system-i386 snake.img
sudo dd if=snake.img of=/dev/sdX bs=512
Replace /dev/sdX with correct device.
(todo) Windows runs rufus.exe
rdtsc.