• Please review our updated Terms and Rules here

Passing parameters/arguments

MykeLawson

Experienced Member
Joined
Mar 21, 2014
Messages
381
So, it has been over 40 years since I last touched CP/M and now the 'retro' in me has a Z-80 running CP/M 2.2. I'm looking to write a program that needs to read the contents of a file. Something akin to 'ProgName A:FileName.txt' where the ProgName will read the contents of FileName.txt from the disk. Hopefully someone has some ideas to help brush away the cobwebs in my head. Thanks,
 
Which language are you planning to use?

Systems that I have used all support the concept of a Command Line $, which is available in RAM at the time that the program is activated. This $ can then be accessed by the program. The filename can be identified, and used to open the file, which can then be read however you need.

Geoff
 
Which language are you planning to use?

Systems that I have used all support the concept of a Command Line $, which is available in RAM at the time that the program is activated. This $ can then be accessed by the program. The filename can be identified, and used to open the file, which can then be read however you need.

Geoff
Thanks Geoff. I will be writing this in native Z-80 assembly language. It would be a standard CP/M program that runs at 0100H. Myke
 
CP/M defaults to putting the command tail at 80H of the zero page with the number of parameters first and then each parameter as a zero terminated string.

CP/M: The Programmers Handbook has a complete example routine starting on page 63 in 8080 assembler.
 
Yes, I've had a look at the book mentioned, which I have to hand. If you need this, you can access/download a copy from the web, full title is 'The Programmers CP/M Handbook' by Andy Johnson-Laird.

The example code mentioned in effect emulates the argc/argv construct of C.

A little way further in the same book are similar examples for finding/opening a file, and then reading data from the file, which you may find useful for jogging your memory.

This is all 8080 of course, if you want Z80 specifically probably others might suggest alternatives, but at this level 8080 should do the job fine.

Geoff
 
Thanks guys. I just downloaded the book from archive.org and it looks like i have a lot of reading and catching up to do. I'm going to copy out the comtail code and do a test assembly just to see where it stands. Then do more reading and dissecting..... Since the archive.org .pdf doesn't lend to a clean copy/paste, I'll post what I pull out here in the post. Myke
 
FYI: You may be interested in an 8080 ==> Z80 translator application:
Hmmmm. Okay; at .LBR file is something I have never fooled with, with respect to how to use it. I have been using zDev Studio v0.8 to write and assemble what little code I have done recently. Then i just load the assembled executable to my Z-80 machine. BTW, my Z-80 is a CPUVille Z-80 machine (http://www.cpuville.com/index.html). Nice machine and I have interfaced it nicely with a STD card cage. All of the cards I have designed and built so far are STD based and I'm liking the results. Lots of wirewrapping! Myke
 
Well, I'll be the first to say this probably is not 100% correct yet. I did the conversion by hand with a few 'books' opened. I want to do a byte by byte comparison between the converted code and the original. Anyway, this is what I have so far......
 

Attachments

  • CommandTail.txt
    5.2 KB · Views: 7
CP/M (the CCP actually) will initialize parts of "page 0" from the commandline that was typed. If the CCP recognizes possible filenames (e.g. "program file1 file2") then it will parse an FCB at 005CH for "file1" and, optionally, an FCB at 006CH for "file2". The entire commandline is also placed in 0080H, with the first byte being the number of characters that follow starting at 0081H. That buffer is NOT null-terminated. In the simple case of the program accepting one file on the commandline, the program typically checks the character at 005DH for being blank, which means no file was given, and (if not blank) then proceeds to call OPEN on 005CH. There are some examples of this in the CP/M manuals, specifically the "Programmer's Guide".
 
Well dang..... Looks like I am further out of the knowledge loop than I thought....... The CP/M for the board I'm using does not have any code to support a printer as there is no printer port hardware. It is basically a stub with a RET. I've got the hardware noodled out, and I'm trying to find a way to send a text file to the printer without having to dork around with the CP/M itself. So I was hoping to put together a PRINT application that took the filename.ext of what I wanted to print, load it via CP/M, and then send it to the printer. Looks like I'm more open to any suggestions.... Thank you all for helping me along with this. Myke
 
What you describe, a PRINT program that accesses your printer port directly, sounds like a good solution to your CP/M not having a printer implemented. I would not mess with all the parsing of 0080H, though, since the CCP will do that for the first (two) filenames on the commandline. You can just test 005DH for not being blank, then do OPEN, READ,... using 005CH as the "FCB". By default, each record of data from the file will be put at 0080H so you can just read and output it to your printer port until you see a Ctrl-Z (and until READ returns an EOF condition - actually, any error).
 
So, if my brain is properly functional, I'm thinking this is what may work:

1. Issue command, as in "PRINT A:TEST.TXT" (only wanting to print one file at a time)

2. CP/M will parse the command, load and execute the PRINT command and load the FCB at 005Ch with the first file

3. Test 005Ch for a non-blank character, and if not blank 'OPEN the file and begin to 'READ' the file

4. Send the data from the first record (sector I assume?) at 0080h to the printer

5. When that has printed, go back and read the next record/(sector?) from 0080h and send that to the printer

6. Rinse, repeat; all the while checking for the EOF (1Ah) character

7. When EOF is detected, 'CLOSE' the file and return control to CP/M
 
That's pretty much right, except that your test for non-blank should be on 005DH, i.e. 005CH+1. The first byte of an FCB is the drive code, then the 11-char filename/type.

I skipped a bunch of details - not sure how familiar you are with BDOS calls. 0080H is the default "DMA address" to use for file transfers. You can set it to some other memory address if you want (must be 128-bytes of "free" memory). If OPEN returns success, then READ calls are used to fill 0080H 128 bytes at a time. A "text" file in CP/M is defined as ending with a Ctrl-Z character, although technically an EOF from READ should be treated the same. So, you loop while READ returns "success" and send each byte in 0080H to your printer device, until you hit Ctrl-Z. CLOSE is actually optional if you never write the file, but it is the "correct" thing to do. If this were MP/M, you really should call CLOSE. Of course, the details of the coed are more complicated than described here - especially when using assembly.
 
Familiar? Let's just say, the last bit of Z-80 type assembly language stuff I ever wrote, was a RAM disk device driver for a TRS-80 Mod I Lev II running LDOS back in 1983. So, I have forgotten more than I probably knew. I have downloaded a lot of books on all things Z-80 and CP/M, but I think I will be getting a hardcopy version of the 'Programmer's Guide'. That seems be be a lot more comprehensive than many of the others.
 
Familiar? Let's just say, the last bit of Z-80 type assembly language stuff I ever wrote, was a RAM disk device driver for a TRS-80 Mod I Lev II running LDOS back in 1983. So, I have forgotten more than I probably knew. I have downloaded a lot of books on all things Z-80 and CP/M, but I think I will be getting a hardcopy version of the 'Programmer's Guide'. That seems be be a lot more comprehensive than many of the others.
Understood, I didn't want to "mansplain" things you already knew. If you're having trouble picturing what this would look like, I can probably find an example. Most CP/M distros come with a DUMP.ASM which is pretty close. That program reads a file and dumps the HEX data to the console, so you would just change the "output" part to dump the raw data to your printer device.
 
Thanks. Nope, I never consider any comments or suggestions as that. You don't know what I may, or may not do. I am always open to suggestions and comments. I am always happy to learn something again, or brand new. As far as the DUMP program, yep, I actually have a copy of the executable and the source, and it seems to be pretty easy to change out the 'print to screen part' and re-route it to a printer. Re-assemble and off to the races..... With some slight de-bugging along the way. But that is how I will learn. And at my age, I want to keep my brain active. Thanks to all of you.
 
So, with the dump.asm file in hand, I'm going through the process of converting the code from 8080 to Z-80 so I can modify it and re-assemble it properly. I figure I also need to pull out the address generation the program does and the program generated CR-LF. Once I get that accomplished, I can add in the printer driver related code and see how well it works. BTW, once it is all working, I'll upload it for any of you that would like to use it. And I need to get hold of an old dot matrix printer (eBay)......
 
Well, looks like I have hit a roadblock of sorts in my 'hand conversion'. There are two 8080 commands that I can't seem to get the right Z-80 syntax correct for: 'SHLD OLDSP' and 'LHLD OLDSP'. From what I gather, it wants to put the CCP stack pointer into HL and at the end, restore it back. I keep getting invalid operand when I try to assemble it...... I'm using zDevStudio for my IDE environment which apparently utilizes Pasmo? I may try a couple other assemblers.... Thoughts?
 
Well, I detest Zilog mnemonics (just sharing)... partly for things like this. But, "LHLD xxx" translates to "LD HL,(xxx)" and "SHLD xxx" is "LD (xxx),HL".
 
Back
Top