A complete Unix/Linux implementation of Microsoft's classic CP/M development tools from the 1980s:
- um80 - MACRO-80 compatible assembler for 8080/Z80
- ul80 - LINK-80 compatible linker
- ulib80 - LIB-80 compatible library manager
- ucref80 - Cross-reference utility
- ud80 - 8080/Z80 disassembler for CP/M .COM files
- ux80 - 8080 to Z80 assembly source translator
These tools can assemble, link, and manage 8080/Z80 assembly code to produce CP/M-compatible .COM executables on modern Linux systems.
pip install um80git clone https://github.com/um80/um80_and_friends.git
cd um80_and_friends
pip install -e .um80 program.mac # Creates program.rel
um80 -o output.rel program.mac # Specify output name
um80 -l listing.prn program.mac # Generate listing file
um80 -g program.mac # Export all symbols as PUBLIC (for debug)
um80 -t program.mac # Truncate symbols to 8 chars (M80 compat)
um80 -e ".z80" program.mac # Execute code before source (set Z80 mode)
um80 --pre macros.mac program.mac # Include file before sourceul80 program.rel # Creates program.com
ul80 -o output.com a.rel b.rel # Link multiple files
ul80 -s program.rel # Generate symbol file (.sym)
ul80 -S symbols.sym program.rel # Specify symbol file name
ul80 -p E000 program.rel # Set origin address (hex)
ul80 --prl program.rel # Output MP/M .PRL formatud80 program.com # Creates program.mac
ud80 -z program.com # Z80 mode
ud80 -e 0200 program.com # Add entry point at 0200h
ud80 -d 0500-05FF program.com # Mark range as dataulib80 -c mylib.lib a.rel b.rel # Create library
ulib80 -l mylib.lib # List contents
ulib80 -p mylib.lib # Show public symbols
ulib80 -x mylib.lib module # Extract module
ulib80 -a mylib.lib new.rel # Add module
ulib80 -d mylib.lib module # Delete moduleucref80 program.mac # Print to stdout
ucref80 -o xref.txt *.mac # Output to fileux80 program.mac # Creates program_z80.mac
ux80 -o output.mac program.mac # Specify output nameMicrosoft MACRO-80 compatible assembler supporting:
- 8080 and Z80 instruction sets
- Macros with parameters (MACRO/ENDM)
- Repeat blocks (REPT, IRP, IRPC)
- Conditional assembly (IF/ELSE/ENDIF, IFDEF, etc.)
- Segments (CSEG, DSEG, ASEG, COMMON)
- PUBLIC/EXTRN for module linking
- Include files
- All standard directives (ORG, EQU, SET, DB, DW, DS, etc.)
Code can be injected before the main source file using -e (inline code) and --pre (include file). Both options can be repeated and are processed in the order specified:
# Set Z80 mode from command line
um80 -e ".z80" program.mac
# Multiple statements using ! separator (DRI notation)
um80 -e ".z80!DEBUG equ 1!BUFSIZE equ 256" program.mac
# Include a file of macros before the main source
um80 --pre stdmacros.mac program.mac
# Combine both, processed left to right
um80 -e ".z80" --pre macros.mac -e "MYVAL equ 42" program.macThis is useful for:
- Switching CPU mode (
.z80or.8080) without modifying source files - Defining conditional assembly symbols (
DEBUG equ 1) - Including project-wide macro libraries
See man um80 for full documentation, or refer to the original Microsoft M80 Manual.
LINK-80 compatible linker that:
- Links multiple .REL relocatable object files
- Resolves external references
- Produces CP/M .COM executables
- Supports COMMON blocks
- Can output Intel HEX format
- Can output MP/M .PRL (Page Relocatable) format
- Provides
__END__symbol for dynamic memory allocation
The linker provides a predefined __END__ symbol that points to the first free byte after all linked segments (code + data + common blocks). This is useful for implementing heap allocation:
EXTRN __END__ ; Import linker symbol
START: LXI H,__END__ ; Load end of program
SHLD HEAP ; Initialize heap pointer
...
DSEG
HEAP: DW 0 ; Heap pointerSee man ul80 for full documentation, or refer to the original Microsoft L80 Manual.
LIB-80 compatible library manager for:
- Creating .LIB library archives
- Listing library contents and public symbols
- Adding/removing/extracting modules
See man ulib80 for full documentation, or refer to the original Microsoft CREF/LIB Manual.
Generates cross-reference listings showing:
- Symbol definitions
- Symbol references by file and line
- PUBLIC and EXTRN declarations
See man ucref80 for full documentation.
8080/Z80 disassembler that:
- Disassembles CP/M .COM files to .MAC source
- Produces output compatible with um80
- Supports both 8080 and Z80 instruction sets
- Allows marking data ranges and entry points
- Generates re-assemblable source code
See man ud80 for full documentation (no Microsoft equivalent exists).
Source-to-source translator that converts Intel 8080 assembly to Zilog Z80 assembly:
- Translates all 8080 instructions to equivalent Z80 mnemonics
- Preserves all comments, labels, and formatting
- Produces byte-identical output when assembled
- Automatically adds
.Z80directive to output - Handles all assembler directives (passes them through unchanged)
Translation examples:
| 8080 | Z80 |
|---|---|
MOV A,B |
LD A,B |
MVI A,42H |
LD A,42H |
LXI H,1234H |
LD HL,1234H |
LDA addr |
LD A,(addr) |
LHLD addr |
LD HL,(addr) |
LDAX B |
LD A,(BC) |
INR A |
INC A |
INX H |
INC HL |
DAD D |
ADD HL,DE |
ADD B |
ADD B |
ADI 10 |
ADD 10 |
JMP addr |
JP addr |
JNZ addr |
JP NZ,addr |
CALL addr |
CALL addr |
CNZ addr |
CALL NZ,addr |
RET / RNZ |
RET / RET NZ |
RLC |
RLCA |
CMA |
CPL |
HLT |
HALT |
PCHL |
JP (HL) |
XCHG |
EX DE,HL |
IN port |
IN A,(port) |
OUT port |
OUT (port),A |
PSW |
AF |
M (memory) |
(HL) |
See man ux80 for full documentation.
| Extension | Description |
|---|---|
| .MAC | Assembly source (MACRO-80 format) |
| .REL | Relocatable object file |
| .COM | CP/M executable |
| .PRL | MP/M Page Relocatable executable |
| .LIB | Library archive |
| .PRN | Assembly listing |
| .SYM | Symbol file |
These tools aim for compatibility with the original Microsoft tools while running on modern Unix/Linux systems:
- Source files use Unix line endings (LF), but CR/LF is also accepted
- File names are case-insensitive for symbols (converted to uppercase)
- Default origin is 0100h (standard CP/M load address)
- Output files are binary-compatible with original CP/M tools
The original Microsoft REL format limits symbol names to 8 characters. um80/ul80 extend this to support symbols up to 255 characters, which is essential for:
- External references with offsets (e.g.,
MEMSEGTBL+2stays intact instead of truncating toMEMSEGTB) - Long descriptive symbol names in modern code
- Compatibility with source code written for other assemblers
Use -t or --truncate to disable this extension for strict M80 compatibility.
See docs/EXTENSIONS.md for technical details on the extended REL format.
um80 supports several Digital Research (DRI) assembly syntax extensions commonly found in CP/M and MP/M source code. These extensions are compatible with DRI's ASM, MAC, and RMAC assemblers.
Multiple instructions can be placed on a single line, separated by !:
PUSH H! PUSH D! PUSH B ; Save registers
POP B! POP D! POP H ; Restore registers
MOV A,B! ORA A! RZ ; Test and return if zeroExtract the low or high byte of a 16-bit value using function-call syntax:
MVI L,LOW(BUFFER) ; Load low byte of address
MVI H,HIGH(BUFFER) ; Load high byte of address
MVI A,LOW(1234H) ; A = 34H
MVI B,HIGH(1234H) ; B = 12HBoth LOW(expr) and HIGH(expr) syntax (with parentheses) and LOW expr / HIGH expr syntax (with space) are supported.
The $ character can be used as a visual separator within numeric literals for readability:
MVI A,1111$0000B ; Binary with separator
LXI H,1$0000H ; Hex: 10000H
MVI B,1$000D ; Decimal: 1000The $ characters are ignored during parsing and do not affect the numeric value.
Symbols can be defined with EQU to represent registers, then used in place of register names:
; Define register aliases using register names
UR EQU B ; UR is an alias for register B
LR EQU C ; LR is an alias for register C
MR EQU E ; MR is an alias for register E
KR EQU H ; KR is an alias for register H (or HL for pairs)
; Use aliases in instructions
MVI MR,0 ; Same as MVI E,0
MOV A,UR ; Same as MOV A,B
INR LR ; Same as INR C
LXI KR,0 ; Same as LXI H,0 (H maps to HL for pairs)For register pair instructions, single register aliases are automatically promoted:
- B or C → BC
- D or E → DE
- H or L → HL
DRI assemblers allowed PUSH A and POP A as synonyms for PUSH PSW and POP PSW:
PUSH A ; Same as PUSH PSW (push A and flags)
POP A ; Same as POP PSW (pop A and flags)Register number assignments (when using numeric values):
| Number | 8-bit Register | 16-bit Pair |
|---|---|---|
| 0 | B | BC |
| 1 | C | DE |
| 2 | D | HL |
| 3 | E | SP |
| 4 | H | - |
| 5 | L | - |
| 6 | M (memory) | - |
| 7 | A | - |
Symbols can be defined as aliases to external symbols with an optional offset, then exported as PUBLIC:
; In library module - define entry points
EXTRN ADD10 ; External symbol from another module
PUBLIC ADD10_SKIP ; Export the alias
; Define alias: ADD10_SKIP is ADD10+2 (skip first instruction)
ADD10_SKIP EQU ADD10+2This is useful for:
- Defining alternate entry points into routines (skipping initialization code)
- Creating symbolic offsets into data structures defined in other modules
- Porting code from assemblers that support this feature (like z88dk)
The alias is resolved at link time:
; In main module - use both symbols
EXTRN ADD10
EXTRN ADD10_SKIP
START: CALL ADD10 ; Call full routine
CALL ADD10_SKIP ; Call at offset (skips first 2 bytes)For more details on these extensions and compatibility notes, see docs/EXTENSIONS.md.
- Man pages:
man um80,man ul80,man ulib80,man ucref80,man ud80,man ux80 - Original Microsoft manuals in
docs/external/:m80.pdf- MACRO-80 assemblerl80.pdf- LINK-80 linkercref_lib.pdf- CREF and LIB-808080asm.pdf- 8080 assembly reference
# Assemble source files
um80 -o main.rel main.mac
um80 -o util.rel util.mac
# Create a library
ulib80 -c mylib.lib helper.rel support.rel
# Link everything together
ul80 -o program.com main.rel util.rel mylib.lib
# Run in CP/M emulator
cpm program.comAfter pip installation, install the man pages manually:
# Find where the package is installed
PKGDIR=$(python3 -c "import um80; print(um80.__path__[0])")
# Copy man pages to system location (requires sudo)
sudo cp "$PKGDIR/../docs/man/"*.1 /usr/local/share/man/man1/
sudo mandbOr view them directly:
man docs/man/um80.1- 80un - Unpacker for CP/M compression and archive formats (LBR, ARC, squeeze, crunch, CrLZH)
- cpmdroid - Z80/CP/M emulator for Android with RomWBW HBIOS compatibility and VT100 terminal
- cpmemu - CP/M 2.2 emulator with Z80/8080 CPU emulation and BDOS/BIOS translation to Unix filesystem
- ioscpm - Z80/CP/M emulator for iOS and macOS with RomWBW HBIOS compatibility
- learn-ada-z80 - Ada programming examples for the uada80 compiler targeting Z80/CP/M
- mbasic - Modern MBASIC 5.21 Interpreter & Compilers
- mbasic2025 - MBASIC 5.21 source code reconstruction - byte-for-byte match with original binary
- mbasicc - C++ implementation of MBASIC 5.21
- mbasicc_web - WebAssembly MBASIC 5.21
- mpm2 - MP/M II multi-user CP/M emulator with SSH terminal access and SFTP file transfer
- romwbw_emu - Hardware-level Z80 emulator for RomWBW with 512KB ROM + 512KB RAM banking and HBIOS support
- scelbal - SCELBAL BASIC interpreter - 8008 to 8080 translation
- uada80 - Ada compiler targeting Z80 processor and CP/M 2.2 operating system
- uc80 - ANSI C compiler targeting Z80 processor and CP/M 2.2 operating system
- ucow - Unix/Linux Cowgol to Z80 compiler
- upeepz80 - Universal peephole optimizer for Z80 compilers
- uplm80 - PL/M-80 compiler targeting Intel 8080 and Zilog Z80 assembly language
- z80cpmw - Z80 CP/M emulator for Windows (RomWBW)