This is a short “getting started” guide for development on CP/M. I’ll assume that you’ve got a CP/M system running; if not, have a look at my guide to setting up an emulated CP/M development system, and that you’re familiar with at least the basics of assembly language programming.
So you’ll need to have at least a text editor, an assembler, and a debugger. Also, I assume that you’re using CP/M 3.x; personally, I find it a bit nicer to use than CP/M 2.2, even though CP/M 2.2 is much more common. Another assumption is that we’re using a Z80; I realise that the majority of CP/M systems likely were 8080-based, but later in CP/M’s life the Z80 became the dominant processor.
The best reference for this area is the “CP/M Plus Programmer’s Guide”; this document covers pretty much all you’ll need to know. Quite often, the documentation from 30 years ago was better than that produced today!
To arguably oversimplify things, the two key concepts in writing assembly language programs for CP/M are:
- Your program should start at address 0100h; this is the start address of the Transient Program Area (TPA).
- You can call system functions via BDOS (Basic Disk Operating System) at address 0005h, after placing the function code in register C. A list of these functions and their input/output parameters is in section 3 of the Programmer’s Guide.
The following trivial program illustrates the above; it simply outputs a ‘q’ to the console, using the BDOS “console output” function.
org 0100h ld c,2 ; BDOS "Console Output" ld e,'q' ; The character to display call 5 ; Call BDOS ret
Using your favourite text editor, create a file called char.z80 with the above content. Using that, you can create char.com with Z80ASM (which is a native Z80 assembler by SLR Systems) and then run it simply like this:
7J>z80asm char 7J>char
(The “7J>” is the command prompt; in this example I’m using user 7 and have a default disk of J. But you can use whatever suits you.)
Alternatively, if you prefer to use the standard Digital Research tools you’ll need to use the MAC macro assembler plus the standard linker, as well macros from Z80.LIB, and you’d need to use different mnemonics in your source code. I’ll leave that as an exercise for the reader. Back when CP/M was still current, that’s how I used to use it, but nowadays I’d much rather use Z80ASM.
Another interesting BDOS function is function #6 for “direct I/O”. This allows you to read raw bytes from the console as well as polling for available input without blocking, depending on the value of the E register. The program listed below is a simple tool that uses this BDOS function to read the keyboard and display the key codes in ASCII. This keeps running until the space bar is pressed. This is a handy way to work out what ASCII sequences that (for example) an arrow key generates for your current terminal type, so you can start to develop some smarter keyboard handling functions in your own programs.
BDOS equ 0005h CONOUT equ 02h DIRIO equ 06h org 0100h ; Output a '?' via direct I/O ld c,DIRIO ; BDOS "Direct Console I/O"" ld e,'?' ; The character to display call BDOS ; Call BDOS ; In a loop, keep reading via direct I/O and displaying via ; direct I/O until we read a space. LOOP: ld c,DIRIO ; print a space ld e,' ' call BDOS ld c,DIRIO ld e,0FDh ; a blocking character read call BDOS call ASCII ; display the ASCII result cp ' ' ; did we get a space? jr nz,LOOP ; nope, so try again ; yep, we got a space ; Output a '.' via direct I/O ld c,DIRIO ld e,'.' call BDOS ret ASCII: push af ; save input value from clobbering srl a ; Move the top nibble into the bottom nibble srl a srl a srl a call DIGIT ; Display the top nibble pop af push af and 0Fh call DIGIT ; Display the bottom nibble pop af ret ; Display the byte in A as a pair of hex digits DIGIT: cp 0Ah ; Is it 0-9 or A-F? jr nc,LETTER add '0' ; Is a digit; Convert it to an ASCII value jr DIGIT2 LETTER: add 'A'-10 ; Is a letter; Convert it to an ASCII value DIGIT2: ld c,CONOUT ld e,a call BDOS ret
The program will display a ‘?’ when it first starts, and it will keep reading characters and displaying ASCII codes until the space bar is pressed. Use it to explore what escape sequences various keys on your system produce.
Hopefully this article has provided you with enough information to get started with writing fantastic software for the thriving CP/M marketplace 🙂