A simulator and assembler for the MIX 1009 computer described in Donald Knuth’s The Art of Computer Programming, Volume 1.
Copyright (c) 2020-2024 Justin Flude <justin_flude@hotmail.com>. Use of this source code is governed by the LICENSE file.
The mix
simulator faithfully mimics the hypothetical computer in all
its aspects, including a full complement of attached I/O devices, as
described in Section 1.3.1: disks, drums, magnetic and paper tapes, a
printer, a card reader, a card punch and a teletype (console). Each
device is backed by a file, or by standard input/output for the
console. The latencies of the devices are accounted for when
calculating execution times, and based upon what might have been
expected in the era of the book’s first publication.
Normally upon starting, the simulator will immediately boot MIX, and
continue to run until a HLT
instruction is executed. It will then
quit. However if the -op
argument is given, the simulator will
prompt the “operator” to press the computer’s GO button before
booting commences, and prompt again on whether to resume execution
following the HLT
, or quit.
The mixal
assembler reads from the program file (encoded as UTF-8)
given as an argument, or from standard input if -
is given, and
outputs simulated punched cards for the card reader, containing the
translated object code. The MIX simulator loads the object code from
the card reader and runs until a HLT
instruction or error condition
is encountered. (Loading of object code from the reader is achieved
by prepending a “loader” card, as described in Exercise 26 of Section
1.3.1.)
Note that this unforgiving implementation of the assembler requires the
input file conform to the MIXAL format as described by the book,
eg. no tabs or other non-MIX characters are allowed, instruction
fields span columns 1-10, 12-15, 17-80, etc. The included mixal.fmt
shell script can correct most formatting errors.
The interrupt facility and supervisor mode for the expanded computer,
described in Exercise 18, Section 1.4.4, can be enabled by giving the
-int
argument to mix
and mixal
, or by setting the environment
variable MIX_ENABLE_INTERRUPTS=y
. A program using this feature, and
other programs of interest, can be found in the examples directory.
$ go test ./... ? github.com/jflude/taocp/cmd/mix [no test files] ? github.com/jflude/taocp/cmd/mixal [no test files] ok github.com/jflude/taocp/mix 0.371s ok github.com/jflude/taocp/mixal 0.056s $ go install ./... $ mixal error: mixal [input file] $ mix -help Usage of mix: -boot int unit to boot from (default 16) -d10 string (default "drum10.mix") -d11 string (default "drum11.mix") -d12 string (default "disc12.mix") -d13 string (default "disc13.mix") -d14 string (default "disc14.mix") -d15 string (default "disc15.mix") -d8 string (default "drum08.mix") -d9 string (default "drum09.mix") -int enable interrupts -op involve the operator -pap string (default "paper.mix") -prt string (default "printer.mix") -pun string (default "punch.mix") -rdr string (default "reader.mix") -t0 string (default "tape00.mix") -t1 string (default "tape01.mix") -t2 string (default "tape02.mix") -t3 string (default "tape03.mix") -t4 string (default "tape04.mix") -t5 string (default "tape05.mix") -t6 string (default "tape06.mix") -t7 string (default "tape07.mix") -trace string output trace to file -trigger int trace addresses above this (default 32) -tty string $ mixal examples/500primes.mixal $ ls -l *.mix -rw-r--r-- 1 justin staff 972 Aug 30 13:19 reader.mix $ mix mix: halted at 3029: HLT (elapsed: 6762025u, idle: 5969153u) $ ls -l *.mix -rw-r--r-- 1 justin staff 2777 Aug 30 13:20 printer.mix -rw-r--r-- 1 justin staff 972 Aug 30 13:19 reader.mix $ cat printer.mix FIRST FIVE HUNDRED PRIMES 0002 0233 0547 0877 1229 1597 1993 2371 2749 3187 0003 0239 0557 0881 1231 1601 1997 2377 2753 3191 ...etc...
As a convenience, the mix.run
script, in a single operation, will
reformat, assemble and execute its input file within a temporary
sandbox, and output (or tail) an I/O device’s backing file.
$ mix.run examples/500primes.mixal mix: halted at 3029: HLT (elapsed: 6762025u, idle: 5969153u) FIRST FIVE HUNDRED PRIMES 0002 0233 0547 0877 1229 1597 1993 2371 2749 3187 0003 0239 0557 0881 1231 1601 1997 2377 2753 3191 ...etc...
mix
can write an execution trace to a file. Register contents are
displayed in decimal and signed octal.
$ mix -trace 500primes.trace examples/500primes.mixal mix: halted at 3029: HLT (elapsed: 6762025u, idle: 5969153u) $ head -36 500primes.trace _______________________________________________________ A: 0 (+00000000000) OP: 3000: IOC 0(18) X: 8775582 (+00041363636) OV: N CI: = I1: 0 (+00000000000) M I2: 0 (+00000000000) 0: +00000005670 I3: 3000 (+00000005670) 1: +00035002044 I4: 0 (+00000000000) 2: +00000000011 I5: 0 (+00000000000) 3: +00003002042 I6: 0 (+00000000000) 4: +00036000510 J: 13 (+00000000015) 5: +00001000006 Device: ..................... Idle! 60000u Elapsed: 661973u _______________________________________________________ A: 0 (+00000000000) OP: 3001: LD1 2050 X: 8775582 (+00041363636) OV: N CI: = I1: 0 (+00000000000) M I2: 0 (+00000000000) 2050: -00000000763 I3: 3000 (+00000005670) 2051: +00000000003 I4: 0 (+00000000000) 2052: +00000000000 I5: 0 (+00000000000) 2053: +00000000000 I6: 0 (+00000000000) 2054: +00000000000 J: 13 (+00000000015) 2055: +00000000000 Device! ..................P.. Idle: 60000u Elapsed: 661974u _______________________________________________________ A: 0 (+00000000000) OP: 3002: LD2 2051 X: 8775582 (+00041363636) OV: N CI: = I1: -499 (-00000000763) M I2: 0 (+00000000000) 2051: +00000000003 I3: 3000 (+00000005670) 2052: +00000000000 I4: 0 (+00000000000) 2053: +00000000000 I5: 0 (+00000000000) 2054: +00000000000 I6: 0 (+00000000000) 2055: +00000000000 J: 13 (+00000000015) 2056: +00000000000 Device: ..................P.. Idle: 60000u Elapsed: 661976u
- The guide for Knuth’s implementation at Stanford, on the IBM S/360
- The manual for UT Austin’s implementation, on the CDC 6000
- James L. Peterson’s Computer Organization & Assembly Language Programming