• Please review our updated Terms and Rules here

Looking for a known-good binary image of CP/M 2.2 BDOS assembled to $E200

cj7hawk

Veteran Member
Joined
Jan 25, 2022
Messages
1,135
Location
Perth, Western Australia.
Just hoping someone has all of this handy, and can assemble me a BDOS for CP/M 2.2 at origin $E200, with the BIOS located at $FC00. ( I just need the BDOS binary, not a BIOS binary ).

I'm having problems converting a BDOS I had to my emulator, since I have to rewrite it for my assembler. I have the CCP working correctly and as expected, but the BDOS binary I create from my own assembler is crashing and rewriting the memory at 0000 thinking it is the allocation vector table, which crashes the emulator. And if I disable that code, it fails elsewhere even when the AV tables aren't relevant, so I think I've converted the assembly file with too many errors.

So if anyone is able to compile me a binary, I'd like to start by checking that my translation of the BDOS from 8080 to z80 and for my assembler doesn't have any errors, for which I can only think to compare Binaries to see where I've translated a statement incorrectly, introduced errors or have the wrong table contents as a quick starting point to debug.

The reason for $E200 for the binary is that I want to concurrently load both BDOS images, and compare the outcomes when things aren't working to see where my own BDOS gives a different result to the DR BDOS.

David
 
Just hoping someone has all of this handy, and can assemble me a BDOS for CP/M 2.2 at origin $E200, with the BIOS located at $FC00. ( I just need the BDOS binary, not a BIOS binary ).

I'm having problems converting a BDOS I had to my emulator, since I have to rewrite it for my assembler. I have the CCP working correctly and as expected, but the BDOS binary I create from my own assembler is crashing and rewriting the memory at 0000 thinking it is the allocation vector table, which crashes the emulator. And if I disable that code, it fails elsewhere even when the AV tables aren't relevant, so I think I've converted the assembly file with too many errors.

So if anyone is able to compile me a binary, I'd like to start by checking that my translation of the BDOS from 8080 to z80 and for my assembler doesn't have any errors, for which I can only think to compare Binaries to see where I've translated a statement incorrectly, introduced errors or have the wrong table contents as a quick starting point to debug.

The reason for $E200 for the binary is that I want to concurrently load both BDOS images, and compare the outcomes when things aren't working to see where my own BDOS gives a different result to the DR BDOS.

David

The attached BDOS binary was assembled at origin $E200 with BIOS assumed to be at $FC00. I use this code with my cp/m 2.2 implementation and it works fine, but if you discover something odd please let me know.
 

Attachments

  • bdos_e200.zip
    2.8 KB · Views: 3
That is perfect, thank you.

I don't know if it's odd, but if it's the standard BDOS binary, then it's perfect. Converting it back to HEX and comparing it to my binary already produces some differences in a few places, so I'll examine why that is and why my BDOS is producing different instructions when I assemble it.

Ironically, I thought I'd do a binary comparison and that would be the test... Turns out binary comparison software is really hard to find, so I had to write my own and it was easier to dump both binaries as hex and then compare... I didn't expect binary comparison software to be so difficult to locate.

David.
 
I've been wanting to write a GUI binary compare program, but just haven't dedicated the time for it. I was envisioning something that displayed a "map" of the files showing segments that differ, possibly using color to indicate degree of difference, and then allowing a "zoom in" on a segment, eventually getting to a display that showed each byte (of the currently zoomed (sub)segment).

Until such time, I also use hexdump (-C) and then find that 'meld' can be effective at showing differences.
 
If you want to go one step further, it would be great to be able to track down the bytes to a specific part of the source file Doug - :) Though putting my assembler in "debug" mode told me what code was going on around the faulty bytes.

Found a few errors - it was where my conversion program converted what looked like it might be a hex value to the new hex format I have, but it wasn't a hex value at all - it was addh: ( a label ) and my system converted it to $add - that wasn't the only error, but all of my errors in conversion to my assembler format were like that - there were just 3 in the end, and some uncertainty around the signature at the start of the BDOS.

OK, I have one part of the assembler code I can't work out what is correct - it's near a patch and looks something like this;

diskwr2: ;if patch1 nop nop lxi h,0 ; ; else ; ; original code ; ;A has vrecord, C=2 if new block or new record# ; dcr c ; dcr c ; jnz noupdate push psw ;save vrecord value call getmodnum ;HL=.fcb(modnum), A=fcb(modnum) ;reset the file write flag to mark as written fcb ani (~fwfmsk)&0ffh ;bit reset mov m,a ;fcb(modnum) = fcb(modnum) and 7fh pop psw ;restore vrecord

The bit about ani (~fwfmsk)&0ffh ;bit reset

FWFMSK is $80, so I assumed the above to be equivalent to AND NOTFWFMSK where NOTFWFMSK=$7F - But the binary files shows this byte to be $00 - eg , AND $00 rather than AND $7F when it comes to assembly without labels.

What should ani (~fwfmsk)&0ffh ;bit reset work out to as a number, if FWFMSL = $80?

Also, shoud the bdos start with the signature bytes, then the jump, or the jump and then the signature bytes, or doesn't it matter as long as the vector at 0005 is correct? ( or to restate the question in another way, what offset into the BDOS does the signature start at? )

Thanks again - I've nearly gotten a good assembling DR BDOS that I've converted to z80 now -
David
 
Also, shoud the bdos start with the signature bytes, then the jump, or the jump and then the signature bytes, or doesn't it matter as long as the vector at 0005 is correct? ( or to restate the question in another way, what offset into the BDOS does the signature start at? )

BDOS starts with 6 bytes that represent the serial number, then a jump to the entry point (over 8 bytes/4 words that collectively is referred to as the 'parameter block'... they appear to be pointers to various error routines).
 
Traditionally, the JMP at location 5 was always to an address of the form XX06. (FYI, the first 6 bytes of the BDOS page are the serial number, although most modern systems just put zeroes there, but access to the serial number was by the JMP at 0005 minus 6 bytes). It was generally discourage for a program to assume XX06, and in fact DDT/SID do not maintain XX06 when they intercept the JMP at 0005. Although, the CP/M 3 RSX facility *does* keep it XX06.

I'm not sure what assembler you're using, but "(~fwfmsk)&0ffh" in modern parlance would be "NOT FWFMSK" in traditional DRI assembler syntax. It should be 7FH, and so your assembler is certainly not processing it correctly.
 
Ironically, I thought I'd do a binary comparison and that would be the test... Turns out binary comparison software is really hard to find, so I had to write my own and it was easier to dump both binaries as hex and then compare... I didn't expect binary comparison software to be so difficult to locate.

Not sure if you're a Windows user, but a tool that I've used for years and find invaluable is a hex editor called HxD. It has a binary compare feature, among other things.
 
FYI, the array of addresses after the BDOS entry JMP are for patching to intercept errors. CP/M 3 provides a cleaner way to control error handling.
 
For reference, here is the first part of the CP/M 2.2 BDOS:
Code:
        db      0,0,0,0,0,0
;
;       enter here from the user's program with function number in c,
;       and information address in d,e
        jmp     bdose   ;past parameter block
;
;       ************************************************
;       *** relative locations 0009 - 000e           ***
;       ************************************************
pererr: dw      persub  ;permanent error subroutine
selerr: dw      selsub  ;select error subroutine
roderr: dw      rodsub  ;ro disk error subroutine
roferr: dw      rofsub  ;ro file error subroutine
;
;
bdose:  ;arrive here from user programs
 
I confess to being perplexed by this discussion. Why not simply do a MOVCPM/SAVE to the proper address and then just excise what you want?
FWIW, I do any CP/M work on 64-bit Linux, running a DOS emulator, running a CP/M emulator. Seems to work just fine. You can use the entire combined toolset of Linux + MSDOS + CP/M.
 
I'm not sure what assembler you're using, but "(~fwfmsk)&0ffh" in modern parlance would be "NOT FWFMSK" in traditional DRI assembler syntax. It should be 7FH, and so your assembler is certainly not processing it correctly.

Hi @labomb the above is the only section of your binary then that was incorrect - The value your assembler comes up with is 00 while mine comes up with 7F. This was the only part of the binary you supplied that I found the be incorrect - ( Mine, of course, was absolutely full of errors, and having yours was instrumental in fixing mine, but you did ask if I found anything specifically related to the supplied file to let you know. ).

Thanks again and kind regards
David
 
Hi @labomb the above is the only section of your binary then that was incorrect - The value your assembler comes up with is 00 while mine comes up with 7F. This was the only part of the binary you supplied that I found the be incorrect - ( Mine, of course, was absolutely full of errors, and having yours was instrumental in fixing mine, but you did ask if I found anything specifically related to the supplied file to let you know. ).

Thanks again and kind regards
David

Good catch, thank you. The assembler I used for that binary is sjasmplus, and I just tried various incantations of the original 'and (not fwfmsk) and 0ffh' instruction and all produce a 0 result. However, changing it to 'and (~ fwfmsk) and 0ffh' as with your code snippet produces the desired result of $7f. According to the docs, the sjasmplus assembler treats '~' as a compliment, while 'not' is a logical not. As is the case with most modern compilers/assemblers, NOT (or !) is used in boolean evaluations, and so given fwfmsk=$80, (not fwfmsk) evaluates to false/0.

Per DR's MAC Macro Assembler documentation with respect to the NOT operator, 'NOT b is the bit-by-bit logical inverse of b'. Reads like a compliment operation to me.

I'm happy that the binary helped!
 
Last edited:
It helped incredibly - and finding a missing byte in your code was entirely unexpected and I'm glad it helped you get your code perfect also - I found about 20 or so bytes in mine that assebled incorrectly and all were due to incorrectly translating labels as hex values. ( hence, one fault typically occured as often as the label was used ). Now I have confidence that my BDOS source is compiling correctly, or reasonable confidence at least... And the BDOS on my system is going into an infinite loop or at least a very large one when it's calculating track numbers... So I think I'm not initialising it correctly. Presently, I have a single BIOS, two BDOS and two CCPs, which I can switch between. The BDOS/CCP I wrote work correctly but that's to be expected as I debugged every line as I went. I'm trying to automate testing between both on my own system so I can work out where incompatabilities come from when I hit them - eg, Wordstar works, as does MBASIC, but ZORK fails. Zork uses random access but the random access on my machine produces the same results tha I see from the BDOS on other machines, so I need to look deeper.

Would you also happen to have a copy of the CCP that you're able to make a binary of? I assemble my CCP at D000 presently, which is where it will remain as I'm writing a particularly large CCP that uses paging for half it's size.

My own CCP seems to be assembling fine and works correctly that I can tell, but if I learnt one thing from checking the BDOS, it's that a binary comparison really helped make sure that the two images are assembling identically... Kind of like a 3K Hash :)

Once I'm done I'll have DR native translated source to z80 for both the BDOS and CCP ( well I do have that now, but checking the translation of my CCP now seems wise also )

Thanks again,
David
 
Would you also happen to have a copy of the CCP that you're able to make a binary of? I assemble my CCP at D000 presently

Here you go, assembled at D000 with BDOS assumed to be at E200 (it's only used for the serialization code).
 

Attachments

  • ccp_d000.zip
    1.6 KB · Views: 2
Back
Top