MaxZ80 - Chapter 17

Let's talk about RDUMP. Here's a screen shot.

6:16 A0:MOUSE>rdump sil:rdump12k.sil -p -l1

Rec    58  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
    1D00: 29 20 0D 0A 63 68 61 72 20 2A 6F 70 3B 0D 0A 7B ) ..char *op;..{
    1D10: 0D 0A 69 66 20 28 2A 6F 70 3D 3D 27 42 27 29 20 ..if (*op=='B')
    1D20: 7B 0D 0A 20 70 75 74 73 74 72 28 22 59 6F 75 20 {.. putstr("You
    1D30: 6D 61 79 20 75 73 65 20 65 69 74 68 65 72 20 2D may use either -
    1D40: 73 6E 6E 20 6F 72 20 2D 6C 6E 6E 2C 20 62 75 74 snn or -lnn, but
    1D50: 20 6E 6F 74 20 62 6F 74 68 21 22 29 3B 0D 0A 20  not both!");..
    1D60: 71 75 69 74 28 29 3B 0D 0A 20 7D 0D 0A 69 66 20 quit();.. }..if
    1D70: 28 21 73 65 61 72 63 68 28 2A 6F 70 2C 22 48 53 (!search(*op,"HS

Dumping SIL:RDUMP12K.SIL - ^C, Esc, X or Q to quit; Any other key to continue

Rec    59  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
    1D80: 4C 50 22 2C 34 29 29 20 7B 0D 0A 20 70 75 74 73 LP",4)) {.. puts
    1D90: 74 72 28 22 55 6E 72 65 63 6F 67 6E 69 7A 65 64 tr("Unrecognized
    1DA0: 20 6F 70 74 69 6F 6E 20 6F 72 20 6E 6F 20 66 69  option or no fi
    1DB0: 6C 65 20 6E 61 6D 65 20 67 69 76 65 6E 21 20 55 le name given! U
    1DC0: 73 65 20 2D 68 20 66 6F 72 20 68 65 6C 70 2E 22 se -h for help."
    1DD0: 29 3B 0D 0A 20 71 75 69 74 28 29 3B 0D 0A 20 7D );.. quit();.. }
    1DE0: 0D 0A 7D 0D 0A 0D 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A ..}.............
    1DF0: 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A ................

6:16 A0:MOUSE>

As you can see, RDUMP "dumps" records of a file, in hex and ASCII. Text files
may be viewed with the builtin TYPE or transient TYPE.COM, so RDUMP is
usually run against .COM files (although our example is showing it dumping
its own source code). RDUMP is worth talking about at this stage because it
introduces several new things and, hopefully, now that you've read sixteen
Chapters, gives you a second look at many old ones.

1. RDUMP is written in a language called SIL which is both a subset of C and
an extension to C. It has several non-standard elements you need to watch out
for. The documentation (SIL.DOC and SILNOTES.DOC) is excellent. For example,
single, not double, ampersands and long vertical marks are used to do logical
comparisons. It's an extension to C because of the supplied relocatable
library SILLIB.REL which among other things has many CP/M specific functions.
We use bdos(), cmndline() and search().

2. RDUMP is our second example of how to link a tiny "Z3HDR" file into an
executable so you can access the Z-System environment segment. It's written
in assembler language and assembled into a .rel file.

 cseg
zentry::
 jp $+0dh
 db 'Z3ENV'
 db 3
 dw 0
 dw zentry
 end

Here's the code that declares the needed variables and loads the environment
address that the command processor stuffs into location hex 109.

int *z3envp;
char *z3env;

z3envp=zentry+9;z3env=*z3envp; /* get z3 environment address */

Here's one of the lines that uses the above.

 if (z3env>0) showname();else putstr("RDUMP");

The showname() function, which needed to be written, includes, among other
things, the following:

char *efcb;

efcbp=*z3envp+@24; /* get ext fcb ptr */
efcb=*efcbp; /* get external fcb */
i=1;
putstr(" ");
while ((*(efcb+i)&@7f)!=' '&i<9) {
 /* mask off hi bit and stop after 8 -
 note: sil uses & instead of && */
 putchar(*(efcb+i)&@7f);
 i++;
 }

The @ in front of the 24 is the way SIL codes hex numbers. Note the "bitwise"
and (&) in the while condition as well as the "logical" and (also &, which in
standard C is &&). This is just "our old friend" External File Control Block
that we saw in Chapter 11 when we were getting the name the BASIC program
SKUNK was invoked with.

3. CP/M can be counted on to put, at hex address 5c, a copy of any string
which starts with the first non-blank character following your command
itself. The string ends as soon as a blank is found. CP/M also puts, at hex
address 6c, a copy of any string following this string. These two addresses
are called FCB1 and FCB2, which stands for File Control Block. RDUMP used to
use this fact to grab the name of the file to be dumped and also an optional
command line parameter. The single original command line parameter was
+offset or -offset, where offset was a decimal number of records. This
supported dumping starting at 3 records past the beginning of a file to the
end of the file or 9 records before the end of a file to the end of the file.
Unfortunately, if you want to have more than one option, you can't use this
FCB approach. The 36 bytes starting at hex 5c are still used by RDUMP, in
fact, quite heavily, as, not only is the name of the file stored here, but
disc allocation block information and a few other things are here as well.

4. We added a sorely needed pause option, -p, as well as ways to abort a
dump.

5. Take a look at SIL.SUB. Here's what it looks like after the comments are
stripped out.

SIL $1 N E P300
SOP $1
XIZ $1
ZDE $1.Z80
ZASM $1
PROLINK READ RDK

The first line compiles the program, generating an .ASM file, which is an
assembler language source file. The next line optimizes this .ASM file. The
next line converts the .ASM into a Zilog mnemonics .Z80 file. The next line
runs the full screen editor ZDE against the file, allowing you to do last
minute adjustments, specifically, letting you change the line that reads

 MACLIB SILZ80
 
to one that reads

*MACLIB SILZ80

a requirement of ZASM, a Z80 assembler. The MACLIB library statement loads
SILZ80.LIB which defines many MACROs that SIL generates. Finally PROLINK
runs, an L80-like linker. PROLINK is well documented here as well. One of the
things PROLINK can do is READ a "link script," in this case, RDK.LNK. This
file has commands that PROLINK understands.

.+
.4/9/2006
ORIGIN 100
LINK Z3HDR,RDUMP12K
SEARCH SILLIB
OUTFIL RDUMP12K
EXIT

So, not only is RDUMP a handy tool, but the tools used to build it are
impressive as well!