| 1 | # bench51 — a TUI 8051 assembler, simulator & debugger |
| 2 | |
| 3 | A small, Keil µVision-style IDE for the Intel 8051 that runs in your terminal. |
| 4 | Write assembly in the built-in editor, assemble it, inspect the listing and |
| 5 | Intel HEX output, then run, pause and single-step the program while watching |
| 6 | registers, SFRs, memory, ports, timers, interrupts and the serial port. |
| 7 | |
| 8 | Built in Rust with [ratatui](https://ratatui.rs). It is a learning tool, not a |
| 9 | cycle-exact replacement for a vendor simulator. |
| 10 | |
| 11 | ----- |
| 12 | |
| 13 | ## Features |
| 14 | |
| 15 | - **Editor** with undo/redo, breakpoint and error markers in the gutter — |
| 16 | or press Ctrl-G to edit in your own `$EDITOR` (vim, nvim, nano, …). |
| 17 | - **Two-pass assembler** for the full 8051 instruction set (all 255 opcodes): |
| 18 | - labels, expressions (`+ - * / MOD AND OR XOR NOT SHL SHR HIGH LOW`, `$`) |
| 19 | - number formats `42`, `2Ah`, `0x2A`, `101010b`, `52o`, `'*'` |
| 20 | - bit addressing (`P1.3`, `ACC.7`, `20h.0`) and all predefined SFR/bit names |
| 21 | - directives `ORG DB DW DS END EQU SET BIT DATA IDATA XDATA CODE CSEG AT` |
| 22 | - generic `JMP`/`CALL` (assembled as `LJMP`/`LCALL`) |
| 23 | - Keil-style `.lst` listing with symbol table, Intel HEX output |
| 24 | - **Simulator** |
| 25 | - all instructions with correct flags (CY, AC, OV, P) and machine-cycle counts |
| 26 | - 4 register banks, 256 bytes IRAM, SFRs, 64K code, 64K XRAM |
| 27 | - ports P0–P3 with latch vs. pin semantics (read-modify-write reads the latch) |
| 28 | - timers 0/1 in modes 0–3, gate and counter inputs |
| 29 | - interrupts: INT0, T0, INT1, T1, serial; two priority levels; edge/level triggers |
| 30 | - UART in modes 0–3 with baud rate timing from timer 1 |
| 31 | - idle and power-down modes (PCON) |
| 32 | - **Debugger**: run / pause, step into / over / out, run to cursor, |
| 33 | breakpoints, changed-value highlighting, memory poke, adjustable speed. |
| 34 | - **Open `.hex` files**: they're disassembled into editable source that |
| 35 | re-assembles to the identical image. |
| 36 | |
| 37 | ## Usage |
| 38 | |
| 39 | ```bash |
| 40 | cargo install --path . # installs the `bench51` binary |
| 41 | |
| 42 | cargo run --release -- examples/serial_hello.asm # open in the TUI |
| 43 | cargo run --release # start with a template |
| 44 | cargo run --release -- firmware.hex # disassemble & debug a HEX file |
| 45 | |
| 46 | # Headless assembly: writes prog.hex and prog.lst |
| 47 | cargo run --release -- --assemble prog.asm |
| 48 | cargo run --release -- --assemble prog.asm -o out.hex --lst out.lst |
| 49 | ``` |
| 50 | |
| 51 | `--clock <MHz>` sets the oscillator frequency used for the elapsed-time display |
| 52 | (default 11.0592). |
| 53 | |
| 54 | ## Keys |
| 55 | |
| 56 | | Key | Action | |
| 57 | | --- | --- | |
| 58 | | F1 | help | |
| 59 | | F2 / Ctrl-S | save (assembling a saved file also writes `.lst` and `.hex` next to it) | |
| 60 | | F3 / Ctrl-O | open `.asm` or `.hex` | |
| 61 | | Ctrl-G | edit in `$EDITOR`; on save & exit the buffer reloads and reassembles | |
| 62 | | F4 | switch Edit ⇄ Debug | |
| 63 | | F7 | assemble, reset and load | |
| 64 | | F5 | run / pause (assembles first if the source changed) | |
| 65 | | F11 / F10 / F12 | step into / step over / step out | |
| 66 | | F8 | run to cursor | |
| 67 | | F9 | toggle breakpoint on the cursor line | |
| 68 | | F6 | reset | |
| 69 | | Ctrl-Q | quit | |
| 70 | |
| 71 | Edit mode: `Alt-1/2/3` switch between Listing, HEX and Errors; `Alt-↑/↓`, |
| 72 | `Alt-PgUp/PgDn` scroll them. The editor uses Emacs-style keys |
| 73 | (`Ctrl-U` undo, `Ctrl-R` redo, `Ctrl-Y` paste). |
| 74 | |
| 75 | Debug mode: `Tab` cycles focus between Source, Memory, Ports and Serial. |
| 76 | Letter shortcuts work too, for terminals that swallow function keys: |
| 77 | `r` run/pause, `s` step, `n` step over, `o` step out, `g` run to cursor, |
| 78 | `b` breakpoint, `x` reset, `i`/`f`/`d`/`c` show IRAM/SFR/XRAM/CODE, |
| 79 | `p` poke memory, `+`/`-` speed, `.` jump to PC, `Esc` pause / back to editor. |
| 80 | |
| 81 | - **Ports**: select a pin and press Space to pull it low from outside (a |
| 82 | button press); the program sees the pin as `latch AND external level`. |
| 83 | - **Serial**: type a line and press Enter to send it (followed by CR) to the |
| 84 | 8051's receiver; everything the 8051 transmits appears above. |
| 85 | |
| 86 | ## Examples |
| 87 | |
| 88 | | File | Shows | |
| 89 | | --- | --- | |
| 90 | | `examples/blink.asm` | port toggling, delay loops, `ACALL`/`RET` | |
| 91 | | `examples/timer_irq.asm` | timer 0 mode 1 interrupt | |
| 92 | | `examples/serial_hello.asm` | UART setup, string output with `MOVC`, echo | |
| 93 | | `examples/button_int0.asm` | edge-triggered INT0, idle mode | |
| 94 | | `examples/bcd_add.asm` | `ADDC` and `DA A` with packed BCD | |
| 95 | | `examples/lookup_movc.asm` | 7-segment table lookup | |
| 96 | |
| 97 | ## Notes and limitations |
| 98 | |
| 99 | - Indirect addressing reaches all 256 bytes of IRAM (8052-style upper 128). |
| 100 | - Serial input has no 9th data bit; in modes 2/3 `RB8` reads 0. |
| 101 | - No 8052 timer 2, external code memory or on-chip peripherals of derivatives. |
| 102 | |
| 103 | ## Development |
| 104 | |
| 105 | ```bash |
| 106 | cargo test # assembler, CPU, peripheral and example-program tests |
| 107 | cargo clippy |
| 108 | ``` |
| 109 | |
| 110 | Code layout: `src/isa.rs` (opcode table shared by everything), `src/asm/` |
| 111 | (assembler, listing, Intel HEX), `src/sim/` (CPU, peripherals, disassembler), |
| 112 | `src/ui/` (ratatui front end). |