SearchA-ZI › IBM 1401

IBM 1401

1959 Open source · MIT Online

This is a from-scratch, in-browser emulator of the IBM 1401 - the machine that put business computing on transistors and magnetic core, and one of the best-selling computers of its era. The 1401 is a variable-length, character/decimal processor: core storage is a string of 6-bit BCD characters, each carrying a separate word mark bit that delimits fields and instructions. There is no fixed word length - an instruction runs from its op code up to the word mark on the next op code.

The emulator models that architecture faithfully: BCD core storage with word marks, the 1-character op + A-address + B-address + d-modifier instruction format, the classic op set (MCW, LCA, SW/CW, Add, Subtract, Compare, Branch, BCE, Write, Halt), the 1403 line printer and the operator console with its sense switches. It boots a demo program that moves banner lines from core storage into the print area and prints them on the paper tape.

Because the entire machine is plain JavaScript, it plugs into the shared debugger: single-step the processor, watch the I-address advance through the variable-length instructions, set breakpoints and word-mark watchpoints, and inspect every character and word mark of core storage live.

Ken Shirriff's IBM 1401 restoration write-ups ↗

Runs on: Web browser

IBM 1401 Online Emulator

Play IBM 1401 using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
IBM 1401 (print demo)IBM 1401IBM 1401openOpen ⛶
IBM 1401 (Sense Switch G on)IBM 1401IBM 1401openOpen ⛶

Machines emulated

Chips

Notes

Embedding

There is no upstream runtime to vendor here — the IBM 1401 core is written from scratch as one plain-global JavaScript module. Vendor it and load it before your boot script:

// the whole machine: CPU + core storage + word marks + 1403 printer + console
<script src="ibm1401.js"></script>   // window.IBM1401 (the Machine constructor)

Boot. Construct the machine on a <canvas> and run your own loop. Because you own the loop, the debugger can pause and step it. One instruction is m.runInsn(); breakpoints are a host-side Set checked against the I-address at each instruction boundary:

var m = new IBM1401(canvas, { senseG: false });
(function loop(){
  for (var i = 0; i < 4000 && m.running; i++) {
    if (bps.has(m.I)) { running = false; break; }  // execution breakpoint
    m.runInsn();                                // exactly one instruction
  }
  m.render();
  requestAnimationFrame(loop);
})();

The machine is plain objects — no wasm heap — so the debugger reaches everything directly:

MemberKindWhat it does
m.runInsn()methodFetch and execute exactly one variable-length instruction; advances the I-address. The single-step primitive.
m.stepInsn(n)methodRun n whole instructions.
m.mem / m.wmfieldCore storage: the BCD character codes and the parallel word-mark bits (side-effect-free to read).
m.I / m.AAR / m.BARfieldThe I-address (program counter), A-address and B-address registers.
m.sensefieldThe six sense switches A..G that Branch tests.
m.poke(a, v)methodWrite one character position through the watchpoint hook m.onWrite.
m.press(id)methodOperator-console action: START, STOP, SCE (single cycle), RESET, or SWx (toggle a sense switch).

Debugger integration

The debugger plug-in (ibm1401-debug.js) reads window.EMU_BOOT and calls EmuKit.defineMachine. Because the whole machine is ordinary JavaScript, single-stepping is just m.runInsn(), and the registers (I-address, A/B-address, op register, the six sense switches) are read and written straight off the machine object.

Breakpoints are a host-side Set the loop checks against the I-address before each instruction. Word-mark watchpoints are wired by installing m.onWrite = fn: every character write goes through m.poke, which calls the hook, so a write to a watched core-storage position pauses the machine promptly.

A new ibm1401 disassembler (/debugger/src/cpus/ibm1401.js) decodes the 1401's variable-length format. Because instruction length is defined by word marks rather than the op code, the decoder reads the live marks through EMU_BOOT.wm(addr) to find where each instruction ends — the same technique cpus/lmc.js uses to reach the true decimal cell value. It renders the 1-char op + A-address + B-address + d-modifier (MCW, LCA, SW, A, S, C, B/BCE, W, H …); anything that is not an op character falls back to .char.

Architecture

The IBM 1401 (1959) was the machine that put business computing on transistors and magnetic core. It is a variable-length, character/decimal processor, unlike the fixed-word binary machines that followed:

  • Core storage — a string of positions, each holding one 6-bit BCD character (a digit, letter or special) plus a separate word-mark bit. Word marks delimit fields and instructions; there is no fixed word length.
  • Instruction format — a 1-character op code (which always carries a word mark) followed by an optional A-address (3 characters), an optional B-address (3 characters) and an optional d-modifier. The machine reads characters until it senses the word mark on the next op code, so the same op appears in 1-, 4-, 5-, 7- or 8-character forms.
  • Registers — the I-address register (instruction address), the A-address and B-address registers, and the operator-console sense switches A..G.
  • Op set — Move Characters (MCW), Load Characters (LCA), Set / Clear Word Mark (SW / CW), Add / Subtract, Compare, Branch and Branch-if-Character-Equal (BCE), Write to the 1403 printer, and Halt.
  • 1403 printer — a 132-column line printer; a Write op prints the print-area positions (201..332) onto the paper tape.

This core is a faithful teaching model: the character storage, word marks, addressing and control flow are modelled fully. Arithmetic is unsigned decimal magnitude with an overflow indicator, and the card reader / punch are stubbed — the operator console and printer are the live I/O. Every character and word mark of state is visible and steppable, which is exactly what makes it a clear debugging target.