8048/8085 disassembler
pgf at mtung.UUCP
pgf at mtung.UUCP
Sat Feb 14 02:28:26 AEST 1987
b
Well, the requests reached critical mass... here's my interactive
disassembler. It may be buggy, it may not be pretty, it may not
even be portable, but it's free... (no makefile, no manpage...)
#-------------cut here (and at the bottom) ----------
# The rest of this file is a shell script which will extract:
# dis.c opc48 opc85
echo extracting - dis.c
cat >dis.c <<'mtung-Fri_Jan_30_11-00-48_EST_1987-'
/*
8085/8048 disassembler Paul Fox, 1982 or so... */
This disassembler is offered as is, no warranty expressed or implied.
It is now in the public domain-- think of me as you use it. :-)
The code is not beautiful, nor was it ever intended to be. It
does do the job. I'm not cleaning it up before sending it out
because I don't feel like testing it again.
The idea is that you start with an Intel hex format file, and just
dive in and disassemble. The targets of jumps and calls are
automatically turned into symbols of the form "LxNNNN" where NNNN
is the hex value of the symbol. Note that it takes at least two
disassemmbly passes to get all the symbols printed as labels,
since labels appearing before their reference won't be in the
table yet on the first pass. As you figure out what the code
does, you add symbol names and values to the symbol table, and
change the names of the "LxNNNN" ones to more meaningful values.
Symbols beginning with "DB" and "DE" cause a switch to data dump
and opcode dump formats, respectively. Useful when you discover
where all the data was stored in the original code.
I'm not sure the 8085 code has been used since I added the 8748 stuff.
*/
#define DIS48 /* define DIS48 or DIS85 for 8048 or 8085 disassembler */
#include <stdio.h>
#define SYMLEN 9
#define NMEMLEN 10
#define SYMTABSIZE 800
#define MEMSIZE 0x2000 /* max size of disassembled program */
#define BYTE 0xff
struct symbol_struct {
int value;
char name[SYMLEN];
} symbol[SYMTABSIZE];
struct symbol_struct *sym;
struct opc {
char nmem[NMEMLEN];
int operands;
} opcode[] = {
#ifdef DIS48
# include "opc48"
#else
# include "opc85"
#endif
};
int first, last, lastsym;
char byte[MEMSIZE];
main()
{
char strng1[20], strng2[20], listfile[20];
char error, filing, opcoding;
int lowbyte, highbyte, cmnd, addr, const, ans;
FILE *list_fd;
struct symbol_struct *getsym();
error = filing = 0;
opcoding = 1;
list_fd = stdout;
lastsym = -1;
load_hexfile();
printf("\n Type 'h' for help...");
while (cmnd = get_command())
{
switch (cmnd)
{
case 'h':
printf("The available commands are:\n");
printf(" l - load symbol table\n");
printf(" s - save symbol table\n");
printf(" d - disassemble\n");
printf(" o - toggle disassembly output between stdout and a listfile\n");
printf(" b - toggle between opcodes and '.byte 0xXX' output\n");
printf(" r - set range of addresses for disassembly\n");
printf(" h - this message\n");
printf(" q - quit\n");
printf(" v - run vi on a file (useful for editing symbol table)\n");
break;
case 'l':
load_symtab();
printf(" %d symbols loaded.\n", lastsym);
error = 0;
break;
case 'r':
get_range();
break;
case 'o':
if (filing)
{
printf(" Listfile closed.\n");
fclose(list_fd);
}
filing = !filing;
if (filing)
{
list_fd = NULL;
while (list_fd == NULL)
{
printf("List file name: ");
scanf(" %s ", listfile);
list_fd = fopen(listfile, "w");
}
printf("Listfile %s opened.",listfile);
}
else
list_fd = stdout;
break;
case 'b':
if (opcoding)
{
printf("Will now default to data bytes...\n");
opcoding = 0;
}
else
{
printf("Will now default to opcode nmemonics...\n");
opcoding = 1;
}
break;
case 'd':
for (addr = first; addr <= last && !error ; addr++)
{
fprintf(list_fd, "\n");
sym = getsym(addr);
if (sym == NULL || sym->name[0] == '0')
{
fprintf(list_fd, "\t");
}
else
{
if (sym->name[0] == 'D' && sym->name[1] == 'B')
opcoding = 0;
else if (sym->name[0] == 'D' && sym->name[1] == 'E')
opcoding = 1;
fprintf(list_fd,"%s:\t",sym->name);
}
if (opcoding)
{
fprintf(list_fd, "%s", opcode[byte[addr] & BYTE].nmem);
switch( opcode[byte[addr] & BYTE].operands )
{
case 0:
break;
case 1:
#ifdef DIS48
if ((byte[addr] & 0x0f) == 0x04)
{ /* then its a "call" or direct "jmp" */
highbyte = (byte[addr] & 0xe0) << 3;
lowbyte = byte[++addr] & BYTE;
const = highbyte + lowbyte;
if (sym = getsym(const))
fprintf(list_fd, " %s", sym->name);
else
{
fprintf(list_fd, " 0x%x", const);
error = !putsym(const);
}
}
else if ((byte[addr] & 0x0f) == 0x06 ||
(byte[addr] & 0x1f) == 0x12)
{ /* it's a page relative jump */
highbyte = (addr & ~0xff); /* this page */
lowbyte = byte[++addr] & BYTE;
const = highbyte + lowbyte;
if (sym = getsym(const))
fprintf(list_fd, " %s", sym->name);
else
{
fprintf(list_fd, " 0x%x", const);
error = !putsym(const);
}
}
else
{
fprintf(list_fd, " 0x%x",
byte[ ++addr] & BYTE);
}
#else
fprintf(list_fd, " 0x%x", byte[ ++addr] & BYTE);
#endif
break;
#ifdef DIS85
case 2:
lowbyte = byte[++addr] & BYTE;
highbyte = byte[++addr] & BYTE;
const = highbyte * 256 + lowbyte;
if (sym = getsym(const))
fprintf(list_fd, " %s", sym->name);
else
{
fprintf(list_fd, " 0x%x", const);
error = !putsym(const);
}
break;
#endif
default:
fprintf(stderr,"Opcode table error!\n");
}
}
else
{
fprintf(list_fd,".byte 0x%x",byte[addr] & BYTE);
}
}
fprintf(list_fd,"\n");
break;
case 's':
save_symtab();
printf(" %d symbols saved.\n", lastsym);
break;
case 'v':
printf("File to edit (with vi): ");
scanf( "%s", strng1);
strcpy(strng2,"vi ");
strcat(strng2,strng1);
system(strng2);
break;
case 'q':
printf("Are you sure you want to quit? ");
ans = getchar();
if ( ans == 'y' )
return;
break;
}
fflush(stdout);
}
}
load_hexfile()
{
char hexfile[20];
FILE *hex_fd;
int line; /* Current input line number */
int bytes; /* Number of bytes to be read on a line */
int sum; /* Checksum of bytes on a line */
int addr; /* Address for input data to be loaded into */
int value; /* Value of data to be loaded */
int mode; /* Mode = 1 means start address is given */
int i; /* Scratch variables */
char c; /* Character scratch variables */
hex_fd = NULL;
while (hex_fd == NULL)
{
printf(" Hex file for disassembly: ");
scanf("%s", hexfile);
hex_fd = fopen( hexfile, "r" );
if (hex_fd == NULL)
printf(" file %s not found...\n",hexfile);
}
/* Mike's code. */
printf("Reading from file %s\n",hexfile);
/*
* Read data from file. Find number of bytes
* to read from a line, read them, and xor
* to get the checksum. Continue until a
* line with a 0 byte count is read. If the
* mode on the last line is 1, read the
* start address and put it into the PC.
*/
line = 0;
bytes = 1;
while (bytes > 0)
{
line++;
if (fscanf(hex_fd,":%2x%4x%2x",&bytes,&addr,&mode) <= 0)
{
printf("Improper program format in line %d\n",line);
fclose(hex_fd);
if (line == 1) first = addr;
return;
}
if (addr >= (MEMSIZE - bytes))
{
printf("Address %x outside allocated memory.\n", addr);
return;
}
if (line == 1) first = addr;
sum = bytes + ((addr/256) & BYTE) + (addr & BYTE) + mode;
for (i = addr; i < addr + bytes; i++)
{
if (fscanf(hex_fd,"%2x",&value) <= 0)
{
printf("Improper program format in line %d at byte %d\n",line,
i - addr);
fclose(hex_fd);
return;
}
sum += value;
byte[i] = value;
last = i;
}
if (fscanf(hex_fd,"%2x",&value) <= 0)
{
printf("Improper program format in line %d at byte %d\n",line,
i - addr);
fclose(hex_fd);
return;
}
sum += value;
if (sum & BYTE)
{
printf("Checksum error in line %d\n",line);
fclose(hex_fd);
return;
}
c = getc(hex_fd);
while (c != '\n') c = getc(hex_fd);
}
}
get_command()
{
char c;
do {
putchar('-');
c = getchar();
} while (c== '\n');
while (getchar() != '\n') ;
return(c);
}
load_symtab()
{
char symfile[20], symname[20];
int rtncode, intval;
FILE *sym_fd;
sym_fd = NULL;
while (sym_fd == NULL)
{
printf(" Symbol table from file: ");
scanf("%s", symfile);
sym_fd = fopen( symfile, "r" );
}
lastsym = -1;
while (( rtncode = fscanf(sym_fd, "0x%x %s\n", &intval, symname)) > 0 )
{
lastsym++;
symbol[lastsym].value = intval;
strcpy(symbol[lastsym].name, symname);
}
if (rtncode != EOF)
printf("!!! Error reading symbol table from %s", symfile);
fclose(sym_fd);
}
save_symtab()
{
char symfile[20];
int i;
FILE *sym_fd;
sym_fd = NULL;
while (sym_fd == NULL)
{
printf(" Symbol table to file: ");
scanf("%s", symfile);
sym_fd = fopen( symfile, "w" );
}
i = 0;
while ( i <= lastsym)
{
fprintf( sym_fd, "0x%x\t%s\n", symbol[i].value, symbol[i].name);
i++ ;
}
fclose(sym_fd);
}
get_range()
{
printf(" Enter start address (hex): ");
scanf("%x", &first);
printf(" Enter finish address (hex): ");
scanf("%x", &last);
}
struct symbol_struct
*getsym(val)
int val;
{
int low, high, mid;
low = 0;
high = lastsym;
while (low <= high)
{
mid = (low + high)/2;
if (val > symbol[mid].value )
low = mid + 1;
else if (val < symbol[mid].value )
high = mid - 1;
else return( &symbol[mid] );
}
return(NULL);
}
putsym(val)
int val;
{
int i, j;
for (j = 0; j <= lastsym; j++)
if( symbol[j].value > val)
break;
if ( ++lastsym == SYMTABSIZE-1 )
{
printf("!!! Too many symbols !!!");
return(0);
}
for (i = lastsym; i >= j; i--)
symbol[i+1] = symbol[i];
symbol[i+1].value = val;
sprintf(symbol[i+1].name, "Lx%x", val);
return(1);
}
mtung-Fri_Jan_30_11-00-48_EST_1987-
echo extracting - opc48
cat >opc48 <<'mtung-Fri_Jan_30_11-00-48_EST_1987-'
"nop", 0,
"xxx", 0,
"outl bus,a", 0,
"add a, ", 1,
"jmp", 1,
"en i", 0,
"xxx", 0,
"dec a", 0,
"ins a,bus", 0,
"in a,p1", 0,
"in a,p2", 0,
"xxx", 0,
"movd a,p4", 0,
"movd a,p5", 0,
"movd a,p6", 0,
"movd a,p7", 0,
"inc @r0", 0,
"inc @r1", 0,
"jb0", 1,
"addc a, ", 1,
"call", 1,
"dis i", 0,
"jtf", 1,
"inc a", 0,
"inc r0", 0,
"inc r1", 0,
"inc r2", 0,
"inc r3", 0,
"inc r4", 0,
"inc r5", 0,
"inc r6", 0,
"inc r7", 0,
"xch @r0", 0,
"xch @r1", 0,
"xxx", 0,
"mov a, ", 1,
"jmp", 1,
"en tcnti", 0,
"jnt0", 1,
"clr a", 0,
"xch a,r0", 0,
"xch a,r1", 0,
"xch a,r2", 0,
"xch a,r3", 0,
"xch a,r4", 0,
"xch a,r5", 0,
"xch a,r6", 0,
"xch a,r7", 0,
"xchd a, at r0", 0,
"xchd a, at r1", 0,
"jb1", 1,
"xxx", 0,
"call", 1,
"dis tcnti", 0,
"jt0", 1,
"cpl a", 0,
"xxx", 0,
"outl p1,a", 0,
"outl p2,a", 0,
"xxx", 0,
"movd p4,a", 0,
"movd p5,a", 0,
"movd p6,a", 0,
"movd p7,a", 0,
"orl a, at r0", 0,
"orl a, at r1", 0,
"mov a,t", 0,
"orl a, ", 1,
"jmp", 1,
"strt cnt", 0,
"jnt1", 1,
"swap a", 0,
"orl a,r0", 0,
"orl a,r1", 0,
"orl a,r2", 0,
"orl a,r3", 0,
"orl a,r4", 0,
"orl a,r5", 0,
"orl a,r6", 0,
"orl a,r7", 0,
"anl a, at r0", 0,
"anl a, at r1", 0,
"jb2", 1,
"anl a, ", 1,
"call", 1,
"strt t", 0,
"jt1", 1,
"da a", 0,
"anl a,r0", 0,
"anl a,r1", 0,
"anl a,r2", 0,
"anl a,r3", 0,
"anl a,r4", 0,
"anl a,r5", 0,
"anl a,r6", 0,
"anl a,r7", 0,
"add a, at r0", 0,
"add a, at r1", 0,
"mov t,a", 0,
"xxx", 0,
"jmp", 1,
"stop tcnt", 0,
"xxx", 0,
"rrc a", 0,
"add a,r0", 0,
"add a,r1", 0,
"add a,r2", 0,
"add a,r3", 0,
"add a,r4", 0,
"add a,r5", 0,
"add a,r6", 0,
"add a,r7", 0,
"addc a, at r0", 0,
"addc a, at r1", 0,
"jb3", 1,
"xxx", 0,
"call", 1,
"ent0 clk", 0,
"jf1", 1,
"rr a", 0,
"addc a,r0", 0,
"addc a,r1", 0,
"addc a,r2", 0,
"addc a,r3", 0,
"addc a,r4", 0,
"addc a,r5", 0,
"addc a,r6", 0,
"addc a,r7", 0,
"movx a, at r0", 0,
"movx a, at r1", 0,
"xxx", 0,
"ret", 0,
"jmp", 1,
"clr f0", 0,
"jni", 1,
"xxx", 0,
"orl bus, ", 1,
"orl p1, ", 1,
"orl p2, ", 1,
"xxx", 0,
"orld p4,a", 0,
"orld p5,a", 0,
"orld p6,a", 0,
"orld p7,a", 0,
"movx a, at r0", 0,
"movx a, at r1", 0,
"jb4", 1,
"retr", 0,
"call", 1,
"cpl f0", 0,
"jnz", 1,
"clr c", 0,
"anl bus, ", 1,
"anl p1, ", 1,
"anl p2, ", 1,
"xxx", 0,
"anld p4,a", 0,
"anld p5,a", 0,
"anld p6,a", 0,
"anld p7,a", 0,
"mov @r0,a", 0,
"mov @r1,a", 0,
"xxx", 0,
"movp a, at a", 0,
"jmp", 1,
"clr f1", 0,
"xxx", 0,
"cpl c", 0,
"mov r0,a", 0,
"mov r1,a", 0,
"mov r2,a", 0,
"mov r3,a", 0,
"mov r4,a", 0,
"mov r5,a", 0,
"mov r6,a", 0,
"mov r7,a", 0,
"mov @r0, ", 1,
"mov @r1, ", 1,
"jb5", 1,
"jmpp @a", 0,
"call", 1,
"cpl f1", 0,
"jf0", 1,
"xxx", 0,
"mov r0, ", 1,
"mov r1, ", 1,
"mov r2, ", 1,
"mov r3, ", 1,
"mov r4, ", 1,
"mov r5, ", 1,
"mov r6, ", 1,
"mov r7, ", 1,
"xxx", 0,
"xxx", 0,
"xxx", 0,
"xxx", 0,
"jmp", 1,
"sel rb0", 0,
"jz", 1,
"mov a,psw", 0,
"dec r0", 0,
"dec r1", 0,
"dec r2", 0,
"dec r3", 0,
"dec r4", 0,
"dec r5", 0,
"dec r6", 0,
"dec r7", 0,
"xrl a, at r0", 0,
"xrl a, at r1", 0,
"jb6", 1,
"xrl a, ", 1,
"call", 1,
"sel rb1", 0,
"xxx", 0,
"mov psw,a", 0,
"xrl a,r0", 0,
"xrl a,r1", 0,
"xrl a,r2", 0,
"xrl a,r3", 0,
"xrl a,r4", 0,
"xrl a,r5", 0,
"xrl a,r6", 0,
"xrl a,r7", 0,
"xxx", 0,
"xxx", 0,
"xxx", 0,
"movp3 a, at a", 0,
"jmp", 1,
"sel mb0", 0,
"jnc", 1,
"rl a", 0,
"djnz r0, ", 1,
"djnz r1, ", 1,
"djnz r2, ", 1,
"djnz r3, ", 1,
"djnz r4, ", 1,
"djnz r5, ", 1,
"djnz r6, ", 1,
"djnz r7, ", 1,
"mov a, at r0", 0,
"mov a, at r1", 0,
"jb7", 1,
"xxx", 0,
"call", 1,
"sel mb1", 0,
"jc", 1,
"rlc a", 0,
"mov r0, ", 1,
"mov r1, ", 1,
"mov r2, ", 1,
"mov r3, ", 1,
"mov r4, ", 1,
"mov r5, ", 1,
"mov r6, ", 1,
"mov r7, ", 1,
mtung-Fri_Jan_30_11-00-48_EST_1987-
echo extracting - opc85
cat >opc85 <<'mtung-Fri_Jan_30_11-00-48_EST_1987-'
"nop", 0,
"lxi b, ", 2,
"stax b", 0,
"inx b", 0,
"inr b", 0,
"dcr b", 0,
"mvi b, ", 1,
"rlc", 0,
".byte 0x08", 0,
"dad b", 0,
"ldax b", 0,
"dcx b", 0,
"inr c", 0,
"dcr c", 0,
"mvi c, ", 1,
"rrc", 0,
".byte 0x10", 0,
"lxi d, ", 2,
"stax d", 0,
"inx d", 0,
"inr d", 0,
"dcr d", 0,
"mvi d, ", 1,
"ral", 0,
".byte 0x18", 0,
"dad d", 0,
"ldax d", 0,
"dcx d", 0,
"inr e", 0,
"dcr e", 0,
"mvi e, ", 1,
"rar", 0,
"rim", 0,
"lxi h, ", 2,
"shld", 2,
"inx h", 0,
"inr h", 0,
"dcr h", 0,
"mvi h, ", 1,
"daa", 0,
".byte 0x28", 0,
"dad h", 0,
"lhld", 2,
"dcx h", 0,
"inr l", 0,
"dcr l", 0,
"mvi l, ", 1,
"cma", 0,
"sim", 0,
"lxi sp, ", 2,
"sta", 2,
"inx sp", 0,
"inr m", 0,
"dcr m", 0,
"mvi m, ", 1,
"stc", 0,
".byte 0x38", 0,
"dad sp", 0,
"lda", 2,
"dcx sp", 0,
"inr a", 0,
"dcr a", 0,
"mvi a, ", 1,
"cmc", 0,
"mov b,b", 0,
"mov b,c", 0,
"mov b,d", 0,
"mov b,e", 0,
"mov b,h", 0,
"mov b,l", 0,
"mov b,m", 0,
"mov b,a", 0,
"mov c,b", 0,
"mov c,c", 0,
"mov c,d", 0,
"mov c,e", 0,
"mov c,h", 0,
"mov c,l", 0,
"mov c,m", 0,
"mov c,a", 0,
"mov d,b", 0,
"mov d,c", 0,
"mov d,d", 0,
"mov d,e", 0,
"mov d,h", 0,
"mov d,l", 0,
"mov d,m", 0,
"mov d,a", 0,
"mov e,b", 0,
"mov e,c", 0,
"mov e,d", 0,
"mov e,e", 0,
"mov e,h", 0,
"mov e,l", 0,
"mov e,m", 0,
"mov e,a", 0,
"mov h,b", 0,
"mov h,c", 0,
"mov h,d", 0,
"mov h,e", 0,
"mov h,h", 0,
"mov h,l", 0,
"mov h,m", 0,
"mov h,a", 0,
"mov l,b", 0,
"mov l,c", 0,
"mov l,d", 0,
"mov l,e", 0,
"mov l,h", 0,
"mov l,l", 0,
"mov l,m", 0,
"mov l,a", 0,
"mov m,b", 0,
"mov m,c", 0,
"mov m,d", 0,
"mov m,e", 0,
"mov m,h", 0,
"mov m,l", 0,
"hlt", 0,
"mov m,a", 0,
"mov a,b", 0,
"mov a,c", 0,
"mov a,d", 0,
"mov a,e", 0,
"mov a,h", 0,
"mov a,l", 0,
"mov a,m", 0,
"mov a,a", 0,
"add b", 0,
"add c", 0,
"add d", 0,
"add e", 0,
"add h", 0,
"add l", 0,
"add m", 0,
"add a", 0,
"adc b", 0,
"adc c", 0,
"adc d", 0,
"adc e", 0,
"adc h", 0,
"adc l", 0,
"adc m", 0,
"adc a", 0,
"sub b", 0,
"sub c", 0,
"sub d", 0,
"sub e", 0,
"sub h", 0,
"sub l", 0,
"sub m", 0,
"sub a", 0,
"sbb b", 0,
"sbb c", 0,
"sbb d", 0,
"sbb e", 0,
"sbb h", 0,
"sbb l", 0,
"sbb m", 0,
"sbb a", 0,
"ana b", 0,
"ana c", 0,
"ana d", 0,
"ana e", 0,
"ana h", 0,
"ana l", 0,
"ana m", 0,
"ana a", 0,
"xra b", 0,
"xra c", 0,
"xra d", 0,
"xra e", 0,
"xra h", 0,
"xra l", 0,
"xra m", 0,
"xra a", 0,
"ora b", 0,
"ora c", 0,
"ora d", 0,
"ora e", 0,
"ora h", 0,
"ora l", 0,
"ora m", 0,
"ora a", 0,
"cmp b", 0,
"cmp c", 0,
"cmp d", 0,
"cmp e", 0,
"cmp h", 0,
"cmp l", 0,
"cmp m", 0,
"cmp a", 0,
"rnz", 0,
"pop b", 0,
"jnz", 2,
"jmp", 2,
"cnz", 2,
"push b", 0,
"adi", 1,
"rst 0", 0,
"rz", 0,
"ret", 0,
"jz", 2,
".byte 0xcb", 0,
"cz", 2,
"call", 2,
"aci", 1,
"rst 1", 0,
"rnc", 0,
"pop d", 0,
"jnc", 2,
"out", 1,
"cnc", 2,
"push d", 0,
"sui", 1,
"rst 2", 0,
"rc", 0,
".byte 0xd9", 0,
"jc", 2,
"in", 1,
"cc", 2,
".byte 0xdd", 0,
"sbi", 1,
"rst 3", 0,
"rpo", 0,
"pop h", 0,
"jpo", 2,
"xthl", 0,
"cpo", 2,
"push h", 0,
"ani ", 1,
"rst 4", 0,
"rpe", 0,
"pchl", 0,
"jpe", 2,
"xchg", 0,
"cpe", 2,
".byte 0xed", 0,
"xri", 1,
"rst 5", 0,
"rp", 0,
"pop psw", 0,
"jp", 2,
"di", 0,
"cp", 2,
"push psw", 0,
"ori", 1,
"rst 6", 0,
"rm", 0,
"sphl", 0,
"jm", 2,
"ei", 0,
"cm", 2,
".byte 0xfd", 0,
"cpi", 1,
"rst 7", 0
mtung-Fri_Jan_30_11-00-48_EST_1987-
#--------- cut here --------
--
Paul Fox, AT&T Information Systems, Middletown NJ.
[ihnp4|vax135]!mtung!pgf (201)957-2698
More information about the Comp.sources.unix
mailing list