Z-80 disassembler
rees at apollo.UUCP
rees at apollo.UUCP
Wed Jul 11 05:20:18 AEST 1984
# The rest of this file is a shell script which will extract:
# Readme dis.c distab.c
echo x - Readme
cat >Readme <<'Godfather_Of_Soul'
This is an el-cheapo Z-80 disassembler, written in C. I wrote it myself.
No comments - tough. It expects to see an input file containing records
of the form
<start_adr> <count> <bytes>
where <start_adr> and <count> are two byte integers, least significant
first, and there are <count> bytes of data. There can be an arbitrary
number of these records.
There is some cruft in here for TRS-80 start addresses, in getbyte().
You can probably ignore it, but may want to take it out.
If you give it a "-a" flag, it produces output suitable for input to
a Z-80 assembler.
Some of the Z-80 instructions are not supported. A special prize for
anyone who adds these.
Let me know if you find any use for this.
Godfather_Of_Soul
echo x - dis.c
cat >dis.c <<'Godfather_Of_Soul'
#include <stdio.h>
extern struct optab {
short op_mask, op_val;
char *op_op;
} optab[], toptab[], ddoptab[], edoptab[], fdoptab[];
struct optab *xopt[] = {
toptab,
ddoptab,
edoptab,
fdoptab,
};
char *f1_op[] = {
"add\ta,", "adc\ta,", "sub\t", "sbc\ta,",
"and\t", "xor\t", "or\t", "cp\t"
};
char *rnam[] = {
"b", "c", "d", "e", "h", "l", "(hl)", "a"
};
char *ssnam[] = {
"bc", "de", "hl", "sp"
};
char *qqnam[] = {
"bc", "de", "hl", "af"
};
char *cctab[] = {
"nz", "z", "nc", "c", "po", "pe", "p", "m"
};
int adr;
char text[64];
int hexcol;
int startadr= -1;
int aflg;
main(ac,av)
int ac;
char *av[];
{
FILE *in;
int c,i;
int f0,f1,f2;
struct optab *opp;
char sbuf[32];
while (ac > 1 && av[1][0] == '-') {
switch (av[1][1]) {
case 'a':
aflg = 1;
break;
}
ac--;
av++;
}
if (ac > 1) {
if ((in = fopen(av[1], "r")) == NULL) {
perror(av[1]);
exit(1);
}
} else
in = stdin;
while ((c = getbyte(in)) != EOF) {
if (aflg)
strcpy(text, "\t");
else {
sprintf(text, "%.4x \t", adr-1);
hexcol = 5;
addhex(c);
}
docode(c, optab, in, text);
printf("%s\n", text);
}
if (!aflg)
printf("%.4x ", adr);
printf("\tend", adr);
if (startadr != -1) {
sphexno(sbuf, "\t%s", startadr);
printf(sbuf);
}
printf("\n");
exit(0);
}
docode(c, opp, in, text)
int c;
struct optab *opp;
FILE *in;
char *text;
{
for (; opp->op_mask != 0; opp++)
if ((c&opp->op_mask) == opp->op_val)
break;
expand(c, opp->op_op, in, text);
}
expand(c, op, in, text)
int c;
char *op, *text;
FILE *in;
{
int i,j;
char *s,sbuf[32];
for (s=op; *s; s++) {
sbuf[0] = '\0';
switch (*s) {
case 'B':
i = getbyte(in);
addhex(i);
sphexno(sbuf, "%s", i);
break;
case '-': /* Relative jump */
i = getbyte(in);
addhex(i);
if (i > 127)
i -= 256;
i += adr;
sphexno(sbuf, "%s", i);
break;
case 'W':
addhex(i = getbyte(in));
addhex(j = getbyte(in));
i = i | (j << 8);
sphexno(sbuf, "%s", i);
break;
case 'S':
sprintf(sbuf, "%s", ssnam[(c>>4)&0x3]);
break;
case 'Q':
sprintf(sbuf, "%s", qqnam[(c>>4)&0x3]);
break;
case 'P':
sprintf(sbuf, "%s", rnam[(c>>3)&0x7]);
break;
case 'R':
sprintf(sbuf, "%s", rnam[c&0x7]);
break;
case 'F':
sprintf(sbuf, "%s", f1_op[(c>>3)&0x7]);
break;
case 'T':
sprintf(sbuf, "%d", (c>>3)&0x7);
break;
case 'X':
c = getbyte(in);
addhex(c);
docode(c, xopt[*(++s)-'0'], in, text);
break;
case 'K':
strcpy(sbuf, (c&0x8) ? "d" : "i");
if (c & 0x10)
strcat(sbuf, "r");
break;
case 'C':
sprintf(sbuf, "%s", cctab[(c>>3)&07]);
break;
default:
sbuf[0] = *s;
sbuf[1] = '\0';
break;
}
strcat(text, sbuf);
}
}
addhex(x)
int x;
{
if (aflg)
return;
addnib(x >> 4);
addnib(x & 0xf);
}
addnib(x)
int x;
{
x += '0';
if (x > '9')
x += 'a' - '9' - 1;
text[hexcol++] = x;
}
getbyte(f)
FILE *f;
{
static int count;
int i,oadr;
char sbuf[32];
while (count == 0) {
oadr = adr;
if ((i = getint(f)) == EOF)
return(EOF);
adr = i;
count = getint(f);
if (adr == 0x40df && count == 2) {
if ((startadr = getint(f)) == EOF)
return(EOF);
count = 0;
adr = oadr;
} else if (adr != oadr) {
sphexno(sbuf, "%s", adr);
if (!aflg)
printf("%.4x ", oadr);
printf("\torg\t%s\n", sbuf);
}
}
adr++;
count--;
if ((i = getc(f)) == EOF) {
printf("Premature EOF\n");
exit(1);
}
return(i);
}
getint(f)
FILE *f;
{
int c,i;
i = getc(f);
if ((c = getc(f)) == EOF)
return(EOF);
else
return(i | (c << 8));
}
sphexno(s, sform, n)
char *s, *sform;
int n;
{
char sbuf[32], *xform;
if (n < 0 || n > 0xffff) {
fprintf(stderr, "sphexno(%d)\n", n);
exit(1);
}
if (n <= 9)
xform = "%d";
else if ((n > 0x10 && n <= 0x9f) || (n > 0x100 && n <= 0x9ff)
|| (n > 0x1000 && n <= 0x9fff))
xform = "%xh";
else
xform = "0%xh";
sprintf(sbuf, xform, n);
sprintf(s, sform, sbuf);
}
Godfather_Of_Soul
echo x - distab.c
cat >distab.c <<'Godfather_Of_Soul'
struct optab {
short op_mask, op_val;
char *op_op;
};
struct optab optab[] = {
0xff, 0, "nop",
0xc0, 0x40, "ld\tP,R",
0xc0, 0x80, "FR",
0xc7, 0x04, "inc\tP",
0xc7, 0x05, "dec\tP",
0xc7, 0x06, "ld\tP,B",
0xc7, 0xc0, "ret\tC",
0xc7, 0xc2, "jp\tC,W",
0xc7, 0xc4, "call\tC,W",
0xc7, 0xc6, "FB",
0xc7, 0xc7, "rst\tT",
0xcf, 0x01, "ld\tS,W",
0xef, 0x02, "ld\t(S),a",
0xef, 0x0a, "ld\ta,(S)",
0xcf, 0x03, "inc\tS",
0xcf, 0x09, "add\thl,S",
0xcf, 0x0b, "dec\tS",
0xff, 0x7, "rlca",
0xff, 0x8, "ex\taf,af'",
0xff, 0x0f, "rrca",
0xff, 0x10, "djnz\t-",
0xff, 0x17, "rla",
0xff, 0x18, "jr\t-",
0xff, 0x1f, "rra",
0xff, 0x20, "jr\tnz,-",
0xff, 0x27, "daa",
0xff, 0x28, "jr\tz,-",
0xff, 0x2f, "cpl",
0xff, 0x30, "jr\tnc,-",
0xff, 0x37, "scf",
0xff, 0x38, "jr\tc,-",
0xff, 0x22, "ld\t(W),hl",
0xff, 0x2a, "ld\thl,(W)",
0xff, 0x32, "ld\t(W),a",
0xff, 0x3a, "ld\ta,(W)",
0xff, 0x3f, "ccf",
0xcf, 0xc1, "pop\tQ",
0xff, 0xc3, "jp\tW",
0xcf, 0xc5, "push\tQ",
0xff, 0xc9, "ret",
0xff, 0xcb, "X0",
0xff, 0xcd, "call\tW",
0xff, 0xd3, "out\t(B),a",
0xff, 0xd9, "exx",
0xff, 0xdb, "in\ta,(B)",
/* 0xff, 0xdd, "X1", */
0xff, 0xe3, "ex\t(sp),hl",
0xff, 0xe9, "jp\t(hl)",
0xff, 0xeb, "ex\tde,hl",
0xff, 0xed, "X2",
0xff, 0xf3, "di",
0xff, 0xfb, "ei",
/* 0xff, 0xfd, "X3", */
0xff, 0xf9, "ld\tsp,hl",
0, 0, "???",
};
struct optab toptab[] = {
0xf8, 0, "rlc\tR",
0xf8, 0x8, "rrc\tR",
0xf8, 0x10, "rl\tR",
0xf8, 0x18, "rr\tR",
0xf8, 0x20, "sla\tR",
0xf8, 0x28, "sra\tR",
0xf8, 0x38, "srl\tR",
0xc0, 0x40, "bit\tT,R",
0xc0, 0x80, "res\tT,R",
0xc0, 0xc0, "set\tT,R",
0, 0, "???",
};
struct optab ddoptab[] = {
0, 0, "???",
};
struct optab edoptab[] = {
0xcf, 0x42, "sbc\thl,S",
0xcf, 0x43, "ld\t(W),S",
0xcf, 0x4a, "adc\thl,S",
0xcf, 0x4b, "ld\tS,(W)",
0xe7, 0xa0, "ldK",
0xe7, 0xa1, "cpK",
0xe7, 0xa2, "inK",
0xff, 0x2b, "dec\tix",
0xff, 0x35, "dec\t(ix+B)",
0xff, 0x44, "neg",
0xff, 0x46, "im\t0",
0xff, 0x4b, "ld\tbc,(W)",
0xff, 0x4d, "reti",
0xff, 0x56, "im\t1",
0xff, 0x5b, "ld\tde,(W)",
0xff, 0x66, "im\t2",
0xff, 0x67, "rrd",
0xff, 0x6f, "rld",
0xff, 0x73, "ld\t(W),sp",
0xff, 0x7b, "ld\tsp,(W)",
0, 0, "???",
};
struct optab fdoptab[] = {
0, 0, "???",
};
Godfather_Of_Soul
More information about the Comp.sources.unix
mailing list