View Full Version : Programs that start at addresses other than 0100H

September 27th, 2015, 07:29 AM
Well..... it seems that my 20k CP/M2.2 system is working as it should be. I've learned a little about ASM and have successfully re-written and run a couple of programs. I have become familiar with ED and the use of an external Word processor for source code. I'm getting better at using Hex numbers and on and on.

I'd like to expand my 20k system to the full 64k system, but prior to that I want to clean up my documentation of my CBIOS and Cold Load Starter. Both of these programs were written in my old assembler. I'd like to re-write them in CP/M. My question is how can an assembled program be written into memory at an address other than 0100H? I'd like to first re-write my CBIOS in CP/M. Assemble that code to another address other than 0100H. Then using a routine I have update the system on disk.

Thanks Mike

September 27th, 2015, 08:18 AM
Frank, peruse the samples in the CP/M "System Alteration Guide". They're very clear on how the setup works.

September 30th, 2015, 12:27 PM
Well.... I've been working with DDT and have found it to be a pretty good resource. And I can use it rather well. I also found the SYSGEN.com program and have learned how to use it. I can easily copy the SYSTEM (first two tracks) from one disk to another. I can also make an image in memory of these tracks. It starts at 0900H. BUT, I have come across a problem. I can use SYSGEN to make a copy of SYSTEM in memory and with my Monitor program I can see that it is there and can make changes, then use SYSGEN to save the new SYSTEM back to the disk.

I then thought that I could use DDT to make these changes to the SYSTEM once it is in memory. I used SYSGEN to make the memory image, stopped SYSGEN and loaded DDT. I then did a -D0900, the system was not there. I reloaded the image with SYSGEN and checked with my Monitor program and there was the SYSTEM. I think that DDT is over writing this area in memory. I read somewhere that DDT loads in two parts. The main piece over writes CCP and the assembler/disassembler just below the main DDT.

I have a 20K CPM setup. So my CCP starts at 3400H and ends at 3C00H. This should be overlaid by DDT and the ass/disass module should be just below 3400H. But I don't think it should be so big that it covers 0900H though 0A00H.

The way I used DDT was to enter DDT, wait for the - prompt and then typed D0900. I expect to see two JMP instructions starting at 0980H but they are not there. Any ideas?

I also found the serial number (?) in my CPM copy it is

02H 016H 00H 00H 01H 069H

I understand the this number has to match a number in MOVCPM, but I have not found this number or where it might be in MOVCPM.


September 30th, 2015, 03:08 PM
Some patch MOVCPM (it's just a matter of modifying a single instruction) to defeat the synchronization test, so your MOVCPM might not have the serial number in it.

But, as you say, DDT does overwrite the CCP. The code for the debugger has to go somewhere and the CCP is the most easily utilized. That's why you have to exit DDT with a "-g0" exit to make sure that the CCP gets reloaded.

September 30th, 2015, 03:50 PM
I must have not explained well enough. For some reason when I load DDT, something, I don't know whether or not it is part of DDT, over writes my SYSTEM image that was copied by SYSGEN. It only occurs when I load DDT, so I was guessing that DDT was writing over the image.

I found two places in MOVCPM.COM that had a number like this. It was
02H 016H 00H 00H 029H 0F3H

I changed both instants to the numbers that I found in CP/M, but still got the sync error. You mentioned changing one instruction. Which one? In CP/M or in MOVCPM?


September 30th, 2015, 04:16 PM
In MOVCPM.COM, as it generates the message (look at 028DH).

Let's turn this into a little exercise for using DDT on MOVCPM.COM. Identify the instruction that needs to be changed--look at the code at 02C1H. Note that a sync error eventually terminates at 0306H by hanging.

September 30th, 2015, 04:37 PM
>I understand the this number has to match a number in MOVCPM, but I have not found this number or where it might be in MOVCPM.

It's in 2 places, in the ccp module and the bdos module.
The serial # here is 00 16 00 00 0C 26
See it this way:

A>ddt movcpm.com
2700 0100

In the ccp, the 6 bytes following USER

0D20 52 45 4E 20 55 53 45 52 00 16 00 00 0C 26 21 10 REN USER.....&!.
0D30 03 0E 00 79 FE 06 D0 11 CE 07 06 04 1A BE C2 4F ...y...........O
0D40 03 13 23 05 C2 3C 03 1A FE 20 C2 54 03 79 C9 23 ..#..<... .T.y.#
0D50 05 C2 4F 03 0C C3 33 03 AF 32 07 00 31 AB 07 C5 ..O...3..2..1...
0D60 79 1F 1F 1F 1F E6 0F 5F CD 15 01 CD B8 00 32 AB y......_......2.
0D70 07 C1 79 E6 0F 32 EF 07 CD BD 00 3A 07 00 B7 C2 ..y..2.....:....
0D80 98 03 31 AB 07 CD 98 00 CD D0 01 C6 41 CD 8C 00 ..1.........A...
0D90 3E 3E CD 8C 00 CD 39 01 11 80 00 CD D8 01 CD D0 >>....9.........
0DA0 01 32 EF 07 CD 5E 02 C4 09 02 3A F0 07 B7 C2 A5 .2...^....:.....
0DB0 06 CD 2E 03 21 C1 03 5F 16 00 19 19 7E 23 66 6F ....!.._....~#fo
0DC0 E9 77 04 1F 05 5D 05 AD 05 10 06 8E 06 A5 06 21 .w...].........!
0DD0 F3 76 22 00 00 21 00 00 E9 01 DF 03 C3 A7 00 52 .v"..!.........R

In the bdos module, it's the first six bytes

1200 00 16 00 00 0C 26 C3 11 08 99 08 A5 08 AB 08 B1 .....&..........
1210 08 EB 22 43 0B EB 7B 32 D6 15 21 00 00 22 45 0B .."C..{2..!.."E.
1220 39 22 0F 0B 31 41 0B AF 32 E0 15 32 DE 15 21 74 9"..1A..2..2..!t
1230 15 E5 79 FE 29 D0 4B 21 47 08 5F 16 00 19 19 5E ..y.).K!G._....^
1240 23 56 2A 43 0B EB E9 03 16 C8 0A 90 09 CE 0A 12 #V*C............
1250 16 0F 16 D4 0A ED 0A F3 0A F8 0A E1 09 FE 0A 7E ...............~
1260 14 83 14 45 14 9C 14 A5 14 AB 14 C8 14 D7 14 E0 ...E............
1270 14 E6 14 EC 14 F5 14 FE 14 04 15 0A 15 11 15 2C ...............,
1280 0D 17 15 1D 15 26 15 2D 15 41 15 47 15 4D 15 0E .....&.-.A.G.M..
1290 14 53 15 04 0B 04 0B 9B 15 21 CA 08 CD E5 08 FE .S.......!......
12A0 03 CA 00 00 C9 21 D5 08 C3 B4 08 21 E1 08 C3 B4 .....!.....!....
12B0 08 21 DC 08 CD E5 08 C3 00 00 42 64 6F 73 20 45 .!........Bdos E

The problem is, sysgen stores these modules in the boot tracks of the disk
so the cp/m os running after boot has to match the serial# of movcpm.

If you edit movcpm.com to your serial# with ddt and save, then you should be able to sysgen a larger
boot system. Of course, do it on a copy so you don't shoot yourself in the foot :)
You can always name the new movcpm1.com and sysgen to a different disk to be safe.

edit: I see more discussion since I read last but those are the two locations of the serial#

September 30th, 2015, 04:40 PM
...or, IIRC, you can simply disable the check in MOVCPM and no one will care.

October 1st, 2015, 10:12 AM
I've been working on this, this morning. I've become familiar with more of the DDT commands and can say that I've learned some. But kinda failed in making MOVCPM work. By 'kinda' I mean, it will work one way, but not by invoking the name MOVCPM.COM

Here's is what I did.
1. I copied the CP/M serial number into the MOVCPM in two places.
2. Then I looked at the code at 02C1. This appears to compare the serial numbers. DE points to 1200H which is one number and HL is loaded from 037AH, which I changed to 00H 12H. Now this routine is comparing the same number and I can trace thru the routine and it compares fine.
3. With this change running MOVCPM still results in a SYNC ERROR
4. Yet if I run MOVCPM from DDT --- G,02C1 it will work.

I see that you are advocating skipping the check, whereas I was trying to make the check work. To that end I zeroed out the JNZ in the check loop, changed C2 5A 02 to 00 00 00. I think that skips the error handler? But this also didn't work.

Need to take a break, before doing more.


October 1st, 2015, 11:16 AM
Mike, this should be a good exercise for you, since MOVCPM is very simple program (if there are any notes on the CP/M OEM redistribution floppy, you should probably read those also). Most of MOVCPM is taken up by the image of the BDOS, BIOS and CCP and relocation map. There's very little executed code there.

I'll also add that executing MOVCPM with no arguments leads to some very bizarre behavior (and always has).

You need to run it with the size of the CP/M you're aiming for and the "S" argument. E.g.


Will generate a 62K CP/M system and leave it in memory for the SAVE command.

October 1st, 2015, 01:44 PM
Well.. got it to work.

Here's is what I did.
1. I copied the CP/M serial number into the MOVCPM in two places.
2. There seems to be two places in MOVCPM that divert the program to the Sync Error. One at 0234H, which is a JNZ to the error. I changed these three bytes to NOPS, so the program would just fall through.
3. The next one is at 02CB, where the program checks the serial numbers for match. Again there is a JNZ to the error, here I changed the address of the jump to proceed is if the match occurred.
4. Now when I enter MOVCPM 48 S, I get a 48K system starting at 0980H.

My OEM distribution CP/M disk, doesn't have any notes on it regarding MOVCPM. I think I was getting balled up, because I was forgetting to add the 'S' on the end of the call, MOVCPM 48, would hang.

So, I think I just have to figure out what size system I want, probably 62K (I still want to keep my monitor program on top), then save the file. Then add my CBIOS and save it with SYSGEN, as it talks about in the alteration guide.

Thanks for the help


October 1st, 2015, 02:59 PM
You know, for a one time use program, what I did will work, but maybe for fun I'd like to get it work as it should. If I have time maybe I'll try and work it out to see if I can get the numbers to match and the program to accept it.


October 1st, 2015, 06:16 PM
Okay, Mike--I'll give you a hint--one of the programs that you'll probably need is "genmod". This takes two binaries assembled 100H bytes apart and constructs a page relocation map to show MOVCPM how to modify addresses. This, incidentally, is the basis of page-relocatable executable files with CP/M Plus and MP/M. Ingenious little solution, that.

October 2nd, 2015, 04:34 AM

Here is a submit file to build movcpm that demonstrates the use of genmod.
Essentially, hex files with a 0 are assembled at 0 and 1 are assembled at 0100h.

mac cpmove
mac boot0
mac ccp0
mac bdos0
mac bios0
save 26 cpm0.com
mac boot1
mac ccp1
mac bdos1
mac bios1
save 26 cpm1.com
genhex cpm0.com
genhex cpm1.com 100
pip cpm10.hex = cpm0.hex,cpm1.hex
genmod cpm10.hex cpm10.com
save 38 cpm10.com
ddt cpm10.com
save 38 movcpm1.com