Getting Started

This guide will help you get started with Tiny8, from installation to running your first programs.

Installation

Requirements

Tiny8 requires Python 3.11 or later. Check your Python version:

python --version

Installing Tiny8

Install Tiny8 using pip:

pip install tiny8

This will install the tiny8 command-line tool and make the Python API available for import.

Verifying Installation

Verify that Tiny8 is installed correctly:

tiny8 --version

You should see the version number printed to the terminal.

Your First Program

Let’s write a simple program that adds two numbers.

Create the Assembly File

Create a new file called add.asm with the following content:

; Simple addition program
; Adds 5 + 3 and stores the result in R16

    ldi r16, 5          ; Load 5 into R16
    ldi r17, 3          ; Load 3 into R17
    add r16, r17        ; Add R17 to R16

done:
    jmp done            ; Infinite loop

Understanding the Code

Let’s break down what each line does:

  • ldi r16, 5 - L oa d I mmediate: Loads the value 5 directly into register 16

  • ldi r17, 3 - Loads the value 3 into register 17

  • add r16, r17 - Adds the contents of R17 to R16, storing the result in R16

  • jmp done - Jumps to the label done, creating an infinite loop

Note

Lines starting with ; are comments and are ignored by the assembler.

Running with the Interactive Debugger

Run your program using the Tiny8 interactive debugger:

tiny8 add.asm

You’ll see a terminal-based interface showing:

  • Source code - Your assembly program with the current instruction highlighted

  • Registers - The 32 general-purpose registers (R0-R31)

  • Status flags - The SREG flags (I, T, H, S, V, N, Z, C)

  • Memory - RAM contents

  • Control information - Program counter (PC), stack pointer (SP), and step count

Debugger Controls

Use these keyboard shortcuts to control execution:

Navigation:

  • l or - Step forward one instruction

  • h or - Step backward one instruction

  • w - Jump forward 10 steps

  • b - Jump backward 10 steps

  • 0 - Go to first step

  • $ - Go to last step

Playback:

  • Space - Toggle play/pause

  • [ - Slower playback

  • ] - Faster playback

Display:

  • r - Toggle showing all registers

  • M - Toggle showing all memory

  • = - Show detailed step information

  • j - Scroll memory view down

  • k - Scroll memory view up

Marks:

  • m + letter - Set a mark at current position

  • ' + letter - Jump to a saved mark

Search/Commands:

  • / - Show help screen

  • : - Enter command mode (for advanced navigation and search)

Exit:

  • q or Esc - Quit

Try stepping through your program with l and watch how the registers change!

Running from Python

You can also run Tiny8 programs from Python code.

Basic Execution

from tiny8 import CPU, assemble_file

# Assemble the program
asm = assemble_file("add.asm")

# Create a CPU instance
cpu = CPU()

# Load the program
cpu.load_program(asm)

# Run the program (with a safety limit)
cpu.run(max_steps=100)

# Read the result
print(f"R16 = {cpu.read_reg(16)}")  # Should print 8

Step-by-Step Execution

For more control, you can step through the program manually:

from tiny8 import CPU, assemble

# Parse assembly code directly
code = """
    ldi r16, 10
    ldi r17, 5
    sub r16, r17
"""
asm = assemble(code)

# Set up and run
cpu = CPU()
cpu.load_program(asm)

# Step through manually
while cpu.pc < len(cpu.program):
    print(f"Step {cpu.step_count}: PC={cpu.pc}")
    cpu.step()
    if cpu.step_count > 10:
        break

print(f"Final result: R16 = {cpu.read_reg(16)}")

Inspecting CPU State

You can inspect various aspects of the CPU state:

# Read registers
value = cpu.read_reg(16)

# Read memory
mem_value = cpu.mem.read(0x0100)

# Check flags
zero_flag = cpu.get_flag(1)  # Z flag
carry_flag = cpu.get_flag(0)  # C flag

# Get trace information
reg_changes = cpu.reg_trace
mem_changes = cpu.mem_trace

Common Assembly Patterns

Loading Immediate Values

ldi r16, 42         ; Load decimal
ldi r17, 0xFF       ; Load hexadecimal
ldi r18, 0b1010     ; Load binary

Working with Memory

; Store register to memory
ldi r16, 100
sts 0x0200, r16     ; Store R16 at address 0x0200

; Load from memory to register
lds r17, 0x0200     ; Load from address 0x0200 into R17

Loops

; Count down from 10 to 0
    ldi r16, 10

loop:
    dec r16             ; Decrement R16
    brne loop           ; Branch if not equal to zero

; Continue execution here

Conditional Branching

; Compare two values
    ldi r16, 5
    ldi r17, 10
    cp r16, r17         ; Compare R16 with R17
    brlo less_than      ; Branch if lower (unsigned)

    ; R16 >= R17
    ldi r18, 1
    jmp done

less_than:
    ; R16 < R17
    ldi r18, 0

done:
    jmp done