Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ Tiny8 is a lightweight and educational toolkit for exploring the fundamentals of


<div align="center">
<img src="https://github.com/user-attachments/assets/6d4f07ba-21b3-483f-a5d4-7603334c40f4" alt="Animated bubble sort visualization" width="600">
<img src="https://github.com/user-attachments/assets/ffbcb2c4-2c3a-469f-b7b7-e6e86eb374da" alt="Animated bubble sort visualization" width="600">
<p><em>Real-time visualization of a bubble sort algorithm executing on Tiny8</em></p>
</div>

## ✨ Features

### 🎯 **Interactive Terminal Debugger**
<img width="600" src="https://github.com/user-attachments/assets/5317ebcd-53d5-4966-84be-be94b7830899" alt="CLI visualizer screenshot">
<img width="600" src="https://github.com/user-attachments/assets/0bbd4382-806e-4b5a-af0b-54d83417fcfb" alt="CLI visualizer screenshot">

- **Vim-style navigation**: Step through execution with intuitive keyboard controls
- **Change highlighting**: See exactly what changed at each step (registers, flags, memory)
Expand Down Expand Up @@ -182,10 +182,10 @@ tiny8 examples/bubblesort.asm -m ani -o sort.gif -ms 0x60 -me 0x80 # Create GI
from tiny8 import CPU, assemble_file

cpu = CPU()
cpu.load_program(*assemble_file("examples/bubblesort.asm"))
cpu.load_program(assemble_file("examples/bubblesort.asm"))
cpu.run()

print("Sorted:", [cpu.read_ram(i) for i in range(100, 132)])
print("Sorted:", [cpu.read_ram(i) for i in range(0x60, 0x80)])
```

## 🔧 CLI Options
Expand Down
34 changes: 14 additions & 20 deletions docs/examples/bubblesort.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ Inner Loop
add r22, r23
ld r24, r22 ; r24 = B

; compare and swap if needed
; compare and swap if A > B (for ascending order)
cp r21, r24
brcc no_swap
st r20, r24 ; swap
st r22, r21
brcs no_swap ; skip if A < B
st r20, r24 ; swap: RAM[addr_A] = B
st r22, r21 ; swap: RAM[addr_B] = A

no_swap:
inc r19
Expand All @@ -118,6 +118,7 @@ For each j:

1. Load adjacent elements (j and j+1)
2. Compare them
3. Swap if first > second (for ascending order)
3. Swap if first > second
4. Advance to next pair

Expand Down Expand Up @@ -225,11 +226,12 @@ Python API
cpu.run(max_steps=50000) # Bubble sort needs many steps!

# Read sorted array
sorted_array = [cpu.mem.read(0x60 + i) for i in range(32)]
sorted_array = [cpu.read_ram(i) for i in range(0x60, 0x80)]
print("Sorted array:", sorted_array)

# Verify it's sorted
assert sorted_array == sorted(sorted_array)
# Verify it's sorted in ascending order
assert all(sorted_array[i] <= sorted_array[i+1]
for i in range(len(sorted_array)-1))
print("✓ Array is correctly sorted!")

Performance Analysis
Expand Down Expand Up @@ -295,10 +297,10 @@ Conditional Swapping

.. code-block:: asm

cp r21, r24 ; Compare values
brcc no_swap ; Skip swap if in order
st r20, r24 ; Perform swap
st r22, r21
cp r21, r24 ; Compare values (A vs B)
brcs no_swap ; Skip swap if A < B (already in order)
st r20, r24 ; Perform swap: RAM[A] = B
st r22, r21 ; Perform swap: RAM[B] = A
no_swap:

Exercises
Expand All @@ -317,7 +319,7 @@ Solutions Hints

**Optimize**: Set a flag when swapping, check it at end of outer loop.

**Descending order**: Change ``brcc no_swap`` to ``brcs no_swap``.
**Descending order**: Change ``brcs no_swap`` to ``brcc no_swap``.

Visualization Tips
------------------
Expand Down Expand Up @@ -370,11 +372,3 @@ Related Examples
* :doc:`linear_search` - Sequential array access
* :doc:`find_max` - Array comparison operations
* :doc:`reverse` - Array manipulation

Next Steps
----------

* Study :doc:`../architecture` for memory model details
* Review :doc:`../instruction_reference` for LD, ST, CP
* Try implementing other sorting algorithms
* Use :doc:`../visualization` to understand algorithm behavior
7 changes: 0 additions & 7 deletions docs/examples/fibonacci.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,3 @@ Related Examples
* :doc:`factorial` - Another iterative calculation
* :doc:`sum_1_to_n` - Similar loop structure
* :doc:`power` - Repeated operation pattern

Next Steps
----------

* Learn about :doc:`../assembly_language` syntax
* Review the :doc:`../instruction_reference` for ADD, MOV, DEC, BRNE
* Try the :doc:`../visualization` tools to see execution flow
9 changes: 0 additions & 9 deletions docs/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,3 @@ Recommended order for learning:
3. **Master control flow**: linear_search, gcd
4. **Tackle algorithms**: bubblesort, power, is_prime
5. **Explore bit operations**: multiply_by_shift, count_bits

Next Steps
----------

* Read the detailed :doc:`fibonacci` walkthrough
* Study the :doc:`bubblesort` algorithm implementation
* Review the :doc:`../architecture` for CPU details
* Practice with :doc:`../visualization` tools
* Explore the :doc:`../api/modules` for Python integration
53 changes: 26 additions & 27 deletions examples/array_sum.asm
Original file line number Diff line number Diff line change
@@ -1,52 +1,51 @@
; Array sum: compute sum of array values [5, 10, 15, 20, 25, 30, 35, 40]
; Array Sum - Sum array elements [5, 10, 15, 20, 25, 30, 35, 40]
; Demonstrates array initialization and iteration
; Registers: R16 = sum, R17 = address, R18 = count, R19 = temp, R20-R21 = init
; Output: R16 = 180 (sum of all array elements)
; Output: R16 = 180

start:
; initialize array at RAM[0x60..0x67] with values [5, 10, 15, 20, 25, 30, 35, 40]
; Initialize array at RAM[0x60..0x67]
ldi r20, 0x60
ldi r21, 5
st r20, r21 ; RAM[0x60] = 5
st r20, r21
inc r20

ldi r20, 0x61
ldi r21, 10
st r20, r21 ; RAM[0x61] = 10
st r20, r21
inc r20

ldi r20, 0x62
ldi r21, 15
st r20, r21 ; RAM[0x62] = 15
st r20, r21
inc r20

ldi r20, 0x63
ldi r21, 20
st r20, r21 ; RAM[0x63] = 20
st r20, r21
inc r20

ldi r20, 0x64
ldi r21, 25
st r20, r21 ; RAM[0x64] = 25
st r20, r21
inc r20

ldi r20, 0x65
ldi r21, 30
st r20, r21 ; RAM[0x65] = 30
st r20, r21
inc r20

ldi r20, 0x66
ldi r21, 35
st r20, r21 ; RAM[0x66] = 35
st r20, r21
inc r20

ldi r20, 0x67
ldi r21, 40
st r20, r21 ; RAM[0x67] = 40
st r20, r21

; compute sum by iterating through array
ldi r16, 0 ; sum = 0 (accumulator)
ldi r17, 0x60 ; address = 0x60 (start of array)
ldi r18, 8 ; count = 8 (number of elements)
; Sum array elements
ldi r16, 0 ; sum = 0
ldi r17, 0x60 ; address
ldi r18, 8 ; count

sum_loop:
ld r19, r17 ; load current array element into r19
add r16, r19 ; add element to sum: sum += array[i]
inc r17 ; advance to next address: address++
dec r18 ; decrement counter: count--
ld r19, r17 ; Load array[i]
add r16, r19 ; sum += array[i]
inc r17 ; address++
dec r18 ; count--

; continue if more elements remain
cpi r18, 0
Expand Down
78 changes: 35 additions & 43 deletions examples/bubblesort.asm
Original file line number Diff line number Diff line change
@@ -1,71 +1,63 @@
; Bubble sort: fill RAM[0x60..0x80] with random values and sort ascending
; Uses PRNG (pseudo-random number generator) to create test data
; Then performs bubble sort by comparing adjacent elements
; Registers: R16 = address, R17 = index/i, R18 = seed/i, R19 = j
; R20-R24 = temp values, R25 = PRNG multiplier
; Output: Sorted array at RAM[0x60..0x80] (32 bytes)
; Bubble Sort - Generate and sort 32 random bytes in ascending order
; Uses PRNG to fill RAM[0x60..0x7F], then bubble sorts in place
; Output: Sorted array at RAM[0x60..0x7F]

; initialize PRNG and loop counters
ldi r16, 0x60 ; base address
ldi r17, 0 ; index = 0
ldi r18, 123 ; PRNG seed (starting value)
ldi r25, 75 ; PRNG multiplier (constant for random generation)
; Initialize PRNG and counters
ldi r16, 0x60 ; Base address
ldi r17, 0 ; Index
ldi r18, 123 ; PRNG seed
ldi r25, 75 ; PRNG multiplier

init_loop:
; generate pseudo-random byte: seed = (seed * 75) + 1
mul r18, r25 ; multiply seed by 75 (low byte only)
inc r18 ; add 1 to avoid zero cycles
; Generate random byte: seed = (seed * 75) + 1
mul r18, r25
inc r18

; store generated value at RAM[base + index]
st r16, r18 ; RAM[0x60 + index] = random value
inc r16 ; advance base pointer
inc r17 ; increment index
st r16, r18 ; Store random value
inc r16
inc r17

; check if we've generated 32 values
ldi r23, 32
cp r17, r23 ; compare index with 32
brne init_loop ; continue if not done
cp r17, r23
brne init_loop

; bubble sort: 32 elements (outer loop runs 31 times)
ldi r18, 0 ; i = 0 (outer loop counter)
; Bubble sort: 32 elements
ldi r18, 0 ; Outer loop: i = 0

outer_loop:
ldi r19, 0 ; j = 0 (inner loop counter - element index)
ldi r19, 0 ; Inner loop: j = 0

inner_loop:
; load element A = RAM[0x60 + j]
ldi r20, 0x60 ; compute address of element A
; Load pair: A = RAM[0x60 + j], B = RAM[0x60 + j + 1]
ldi r20, 0x60
add r20, r19
ld r21, r20 ; r21 = value of element A
ld r21, r20 ; r21 = A

; load element B = RAM[0x60 + j + 1]
ldi r22, 0x60 ; compute address of element B
ldi r22, 0x60
add r22, r19
ldi r23, 1
add r22, r23 ; address = 0x60 + j + 1
ld r24, r22 ; r24 = value of element B
add r22, r23
ld r24, r22 ; r24 = B

; compare and swap if A > B (ascending order)
cp r21, r24 ; compare A with B
brcc no_swap ; skip swap if A < B (carry clear)
; Swap if A > B (ascending order)
cp r21, r24
brcs no_swap ; Skip if A < B
st r20, r24 ; RAM[addr_A] = B
st r22, r21 ; RAM[addr_B] = A

no_swap:
; advance to next pair of elements
inc r19 ; j++
ldi r23, 31 ; check if j < 31 (last valid pair)
inc r19
ldi r23, 31
cp r19, r23
breq end_inner ; exit inner loop if j == 31
breq end_inner
jmp inner_loop

end_inner:
; advance outer loop counter
inc r18 ; i++
ldi r23, 31 ; check if i < 31 (need 31 passes)
inc r18
ldi r23, 31
cp r18, r23
breq done ; exit if all passes complete
breq done
jmp outer_loop

done:
jmp done ; infinite loop (halt)
jmp done
Loading