View Full Version : CP/M 2.2 BDOS functions

October 15th, 2016, 10:06 AM
I have been attempting to use and learn all the CP/M 2.2 BDOS function calls. They are all new to me. Anyway, one item I have noticed is that although most references to the functions tell me what registers are used for input and which return output. BUT.... I have not found any information on which registers are used in the function itself. The reason I mention this is that in some of my code I made a BDOS call that uses just A and C, function 01H console input and I have found that register B is changed. I was using B prior to the call. So, since I have not found which registers are involved with a BDOS function call, should I push all the registers to stack each time I make a function call, or..... Thanks Mike

October 15th, 2016, 10:33 AM
To refresh my memory, I just glanced in my Programmer's CP/M Handbook and yes, the CP/M 2.2 BDOS calls do not preserve registers so it is up to the programmer to save / restore them across the calls.
It also indicates the stack is a good place to save them because BDOS uses it's own stack.

Larry G

October 15th, 2016, 10:35 AM
Push all the registers that aren't being returned from BDOS. Most of the CP/M code I have looked at includes "PUSH H! PUSH D! PUSH B;" before calling BDOS with matching POPs after.

October 15th, 2016, 10:59 AM
If you're after speed, push/pop only the registers you need to save.

October 15th, 2016, 11:21 AM
Thanks for the responses. These function calls are kinda handy and simple to use. I've been working on a simple controller that has a 2k EEPROM in it and I'm currently working on a routine to program the EEPROM. Anyway, I'm getting familiar with DDT also and noticed an oddity. Using the DDT Move command, I have found an easy way to move blocks of data around, but if I try to do


This should move a 2k block from F800 - FFFF to 1800 - 1FFF, but the machine hangs and runs on. Yet


Which is one memory location less, will work just fine. There must be a roll over problem or something here? Not sure. Thanks Mike

October 15th, 2016, 11:52 AM
Yes, DDT doesn't check for 16-bit "wrap", so your move goes on forever. I think that SID or ZDT may figure the end conditions better.

October 15th, 2016, 12:08 PM
In a nutshell, the command:
Byte moved from s to d then both are incremented and s is compared against f. When s > f then done. When s gets incremented from FFFF to 0000 then checked, it's never > f so move continues indefinitely.
To fix, check condition needs to be done for equal before incrementing.

October 15th, 2016, 12:48 PM
What's puzzling is why DRI decided to do the move command in this way--the DEC versions of DDT (and ODT) don't share the syntax.

It would have made more sense to say M source, destination, count. It's unambiguous and there are no problems with wraparound.

October 20th, 2016, 12:40 PM
Continuing with this, I have been rewriting some of my old assembly language programs. The ones that I wrote using my homemade assembler. Basically what I've been doing is to replace all the I/O routines with BDOS function calls. This has been working pretty good until one of my routines that that inputs a character, but does not echo it back. Function #1 echos the character back. So I though of trying Function Call #10, but this one recognizes some control characters and acts on them, which I do not want and echos back the string. So, I just want to input a character from my console, place it the accumulator, don't echo it back and quit. I don't see a BDOS call that does that. So, must I write a primitive console input to cover this?

Reason I need this is that my Televideo 920C function keys (F-F11) return a CONTROL A, an ascii character corresponding to the key number and a CR. I want to grab the Televideo function key but not to echo back anything. Any ideas, Mike.

October 20th, 2016, 02:01 PM
Under CP/M 2, the simplest way is to use BDOS 6 in a tight loop:

MVI C, 6

Under CP/M 3, you can simplify to

MVI C, 6

October 20th, 2016, 03:05 PM
I'm using cpm2.2. GGGeeeezzzz! I completely missed the point that the accumulator returns the character if it is not 0H or FFH. Thanks for the help works good now. Mike