This program implements a Universal Turing Machine emulator following the ZHAW encoding scheme.
- Input/Output: implemented in C
- Core simulation: implemented in x86-64 assembly
- Stack: uses a dedicated TM stack region, switched via
rspsave/restore
- Architecture: x86-64 (AMD64)
- Syntax: Intel (
.intel_syntax noprefix) - ABI: System V AMD64
rsp-> TM private stack during simulation, C stack otherwiser12->TMState *pointer (persists across entire function)eax-> current TM state (q_i)ebx-> head position on tapeedx-> current tape symbol under headr13d-> transition count (loop bound)r14-> transition array scan pointerr15d-> search loop index (tm_step)r8-> cached tape pointer (tm_runonly)r9d-> cached tape length (tm_runonly)rcx-> transition scan pointer (tm_runonly)esi/edi-> scratch for write symbol / new state
High addresses
┌──────────────────┐
│ C stack │ normal call frames
│ callee-saved │ rbp, rbx, r12–r15
├──────────────────┤ <- saved_c_rsp
│ │
│ (gap) │
│ │
├──────────────────┤ <- tm_stack_top (rsp during simulation)
│ TM stack │ 64 KiB heap-allocated
└──────────────────┘
Low addresses
- Read TM encoding (C) from binary string, file, or decimal Gödel number
- Parse encoding into transition table + optional tape input (C)
- Initialise tape (128 KiB, blank-filled), place input at centre (C)
- Call assembly function
tm_steportm_run - For each simulation step:
- save C stack pointer, switch
rspto TM stack - read tape symbol at head position
- linear scan transitions for match on
(state, symbol) - match found -> write new symbol, update state, move head, increment step counter
- no match -> halt (reject)
- state = q2 -> halt (accept)
- save C stack pointer, switch
- Step mode (
tm_step):- execute one transition, switch stack back, return to C
- C prints state, tape, head position
- repeat until halt or user quits
- Run mode (
tm_run):- loop entirely on TM stack until halt
- single stack switch back to C on completion
- Print final result: state, tape content, unary count (C)
- States:
q_i->0repeated i times (q1 = start, q2 = accept) - Symbols:
X_j->0repeated j times (X1 =0, X2 =1, X3 = blank) - Directions:
D_m->0repeated m times (D1 = L, D2 = R) - Transition
δ(q_i, X_j) = (q_k, X_l, D_m)->0^i 1 0^j 1 0^k 1 0^l 1 0^m - Transitions separated by
11 - TM code and tape input separated by
111 - Gödel number: prepend
1to binary, interpret as decimal integer
--binary <str>-> binary encoding string directly--file <path>-> read binary encoding from file--decimal <num>-> Gödel number (arbitrary precision)--input <str>-> tape input as0/1characters--input-unary <n>-> tape input as n ones (for unary-coded problems)
--step-> interactive single-step (Enter = step,r= run,q= quit)--run-> execute all steps without pause (default)--max-steps <n>-> safety limit to prevent infinite loops (default 100000)
make # produces ./utm
make clean # remove build artifacts
make test # run smoke tests with T1/T2 from lectureRequires: gcc, make on x86-64 Linux.
- T1:
010010001010011000101010010110001001001010011000100010001010(Gödel:1480103890654955658) - T2:
1010010100100110101000101001100010010100100110001010010100(Gödel:185943403774763668)
- The TM is deterministic (first matching transition wins)
- The simulation stack is physically separate from the C call stack
- Step mode switches
rspback to the C stack before each print call - Tape bounds are clamped (no dynamic growth)