An MCS-48 Disassembler
Der-Ru Sheu
sheu at gitpyr.gatech.EDU
Wed Jan 21 02:08:21 AEST 1987
Attached is a disassembler for Intel MCS-48 family single component micro-
processors. I wrote this a while ago, and hereby put it into the public
domain.
This program would accept an Intel Hex format file, and produce a listing
type file (with address and opcode) or assembly type file (with -a option).
To compile it, just use "cc main.c decode.c utility.c" (UCB CC) or
"cl main.c decode.c utility.c" (MicroSoft C).
- - - - - - - - - - - - - - - - CUT HERE - - - - - - - - - - - - - - - -
echo X - main.c
cat << "#### END OF MAIN.C ####" > main.c
#include <stdio.h>
/* Intel (TM) 8038 family single component u-p machine code disassembler
* By: Sheu, Der-Ru; March 12, 1985
*
* Command line options:
* -s hex# sets the starting address (default 0)
* -e hex# sets the ending address (default 2K)
* -a sets output in assembly format (default 0)
*
* Stdin and Stdout are always used as in/output, use redirection for
* file i/o. Input should be in the Intel HEX format.
*
*/
int pc_start = 0; /* Command options */
int pc_end = 0x800;
int asm = 0;
main(argc, argv)
int argc;
char *argv[];
{
int count, New, c, i, pc;
char addr[6];
int new_pc, byte1, byte2, two_byte;
/* -1- parse command line parameters */
for (i=1; i<argc;)
switch (argv[i++][1])
{ case 'a':
case 'A':
asm = 1;
break;
case 's':
case 'S':
if (i >= argc) usage();
pc_start = readhex(argv[i++]);
break;
case 'e':
case 'E':
if (i >= argc) usage();
pc_end = readhex(argv[i++]);
break;
default: usage();
}
/* -2- now begin disassemblying */
for (pc = 0; pc < pc_start;)
if (!(get_op(pc, &pc, &byte1))) exit(0);
if (!(get_op(pc, &pc, &byte1))) exit(0);
for (; pc <= pc_end;)
if (!(get_op(pc, &new_pc, &byte2))) exit(0);
else
{ if (new_pc == (pc+1))
two_byte = decode(pc, byte1, byte2, asm);
else
{ decode(pc, byte1, 0, asm);
two_byte = 0;
printf("\n");
}
printf("\n");
if (two_byte)
{ if (!(get_op(new_pc, &pc, &byte1))) exit(0); }
else
{ pc = new_pc;
byte1 = byte2;
}
}
printf("\n");
}
readhex(string)
char string[];
{
int c, i, j;
for (i=j=0; ; i++)
{ c = string[i];
if ((c >= '0') && (c <= '9')) c -= '0';
else if ((c >= 'A') && (c < 'G')) c -= 'A' + 10;
else if ((c >= 'a') && (c < 'g')) c -= 'a' + 10;
else break;
j <<= 4;
j += c;
}
return(j);
}
usage()
{
fprintf(stderr, "Usage: dee [-a] [-s starting] [-e ending]\n");
exit(-1);
}
#### END OF MAIN.C ####
echo X - decode.c
cat << "#### END OF DECODE.C ####" > decode.c
#include <stdio.h>
#include "tables.h" /* Mnemonis and opcode tables */
int byte1, byte2, Hnibble, Lnibble, i, c;
/*
* Routine to decode an instruction "byte1 byte2" with address "pc".
* calls Dumpbyte to dump a byte
* calls lookup to look up in the opcode table
*/
decode(pc, byte1, byte2, asm)
int pc, byte1, byte2, asm;
{
if (!asm)
{
printf(" ");
Dumpbyte( pc >> 8 ); /* Dump address */
Dumpbyte( pc & 0X0FF );
printf(" ");
Dumpbyte(byte1); /* Dump code */
printf(" ");
if (_Byte[byte1])
Dumpbyte(byte2);
else printf(" ");
}
Hnibble = byte1 >> 4; /* Extract the higher */
Lnibble = byte1 & 0X0F; /* and lower nibbles */
printf(" ");
lookup(); /* and look it up */
if (_Byte[byte1])
if (_Byte[byte1] == 1) Dumpbyte(byte2);
else
{ byte2 += ((pc--) & 0XF00);
Dump(byte2>>8);
Dumpbyte(byte2 & 0X0FF);
}
return(_Byte[byte1]);
}
lookup()
/* Lookup: look up the opcode table
* input - Lnibble and Hnibble
* output - mnemonics are printed
*/
{
if ( (!(Lnibble & 0X08) && (Lnibble & 0X02)) || (Lnibble == 5) )
printf("%s",Row[trans1[Lnibble]][Hnibble]);
/* REGULAR opcodes */
else if (Lnibble == 4) { /* CALL or JUMP */
if (Hnibble & 0X01) printf("CALL ");
else printf("JMP ");
Dump( (Hnibble & 0X0F) >> 1 );
}
else if ( (byte1 & 0XFE) == 0X0C0 || (byte1 & 0XFE) == 0X0E0 )
printf("???"); /* unknown opcodes */
else if ( ((Hnibble != 0) && (Hnibble != 3) && (Hnibble != 8) &&
(Hnibble != 9) ) || (Lnibble > 11 ) ) {
i = 0;
while ( (c = Col[Hnibble][i++]) != '\0') {
switch (c) {
case 'r':
Dump (Lnibble & 0X07);
break;
case '@':
if (Lnibble < 8) printf("@");
break;
case 'p':
Dump(Lnibble & 0X03);
break;
default:
putc( c, stdout );
break;
}
}
}
else printf("%s", ir[ trans2[Hnibble]][trans3[Lnibble]]);
}
Dumpbyte( i )
/* Dumpbyte: dump a byte stored in i */
int i;
{
Dump( i >> 4 );
Dump( i & 0X0F );
}
Dump(nibble)
/* Dump: dump a nibble (4 bits, a hex digit) */
int nibble;
{
if( (nibble >= 0) && (nibble <= 9)) putchar( nibble + '0');
else putchar(nibble + 'A' -10);
}
#### END OF DECODE.C ####
echo X - utility.c
cat << "#### END OF UTILITY.C ####" > utility.c
/* utility module:
*
* GET_OP: get the next opcode in the Intel Hex format.
* KEEP: keep addresses.
* SAVE: save the addresses.
*/
#include <stdio.h>
static int check_sum = 0;
static int power_up = 1;
static int byte_max = 0; /* Force read new line */
static int byte_count = 1;
get_nibble()
{
int i;
i = getchar();
if ((i >= '0') && (i <= '9')) return (i - '0');
if ((i >= 'A') && (i <= 'F')) return (i - 'A' + 10);
if ((i >= 'a') && (i <= 'f')) return (i - 'a' + 10);
printf("\nUnexpected character found in the input file!!!\n");
return(0);
}
get_byte()
{ int i;
i = get_nibble() << 4;
i += get_nibble();
check_sum += i;
return(i);
}
get_pc(pc_)
int *pc_;
{ int i;
if (!power_up)
{
i = get_byte();
if (!check_sum) fprintf(stderr, "Check sum error at PC = $%4x", *pc_);
check_sum = 0;
}
power_up = 0;
while (1)
{
while ( (i = getchar()) != ':')
if (i == EOF) return(0);
byte_count = 1;
byte_max = get_byte();
*pc_ = get_byte() << 8;
*pc_ += get_byte();
if ( !(i = get_byte()) ) return(1);
if ( i == 1 ) return(0);
fprintf(stderr, "Unknown record type found at PC = $%4x", *pc_);
}
}
get_op(pc, pc_, op_)
int *pc_, *op_;
{
if (byte_count >= byte_max)
{ if (!get_pc(pc_)) return(0); }
else
{ *pc_ = ++pc;
byte_count++;
}
*op_ = get_byte();
return(1);
}
static char buff[400][6];
static int ptr = 0;
keep(addr)
char addr[6];
{
int i;
for (i=0; i<6; i++) buff[ptr][i] = addr[i];
ptr++;
}
save(fp)
FILE *fp;
{
int i;
for(i = 0; i <= ptr; i++) fprintf( fp, "%s", buff[i] );
}
#### END OF UTILITY.C ####
echo X - tables.h
cat << "#### END OF TABLES.H ####" > tables.h
int _Byte[256] = { /* byte table */
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 2, 0, 1, 0, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 2, 0, 1, 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static int trans1[8] = { -1, -1, 0, 1, -1, 2, 3, 4 };
/* translation table for *Row */
static char *Row[5][16] = {
{ "???", "JB0 ", "???", "JB1 ", "MOV A,T", "JB2 ", "MOV T,A", "JB3 ",
"???", "JB4 ", "???", "JB5 ", "???", "JB6 ", "???", "JB7 " },
{ "ADD A,#", "ADDC A,#", "MOV A,#", "???", "ORL A,#", "ANL A,#", "???", "???",
"RET", "RETR", "MOVP A, at A","** JMPP @A **", "???","XRL A,#", "MOVP3 A, at A", "???" },
{ "EN I", "DIS I", "EN T", "DIS T", "START E", "START T", "STOP T", "ENT0 CLK",
"CLR F0", "CPL F0", "CLR F1", "CPL F1", "SEL RB0", "SEL RB1", "** SEL MB0 **", "** SEL MB1 **" },
{ "???", "JTF ", "JNT0 ", "JT0 ", "JNT1 ", "JT1 ", "???", "JF1 ",
"JNI ", "JNZ ", "???", "JF0 ", "JZ ", "???", "JNC ", "JC " },
{ "DEC A", "INC A", "CLR A", "CPL A", "SWAP A", "DA A", "RRC A", "RR A",
"???", "CLR C", "CPL C", "???", "MOV A,PSW","MOV PSW,A","RL A", "RLC A" }
};
static char *Col[16] = {
"MOVD A,Pp","INC @Rr", "XCH A, at Rr", "MOVD Pp,A","ORL A, at Rr", "ANL A, @Rr", "ADD A, at Rr", "ADDC A, at Rr",
"ORLD Pp,A","ANLD Pp,A","MOV @Rr, A", "MOV @Rr,#", "DEC Rr", "XRL A, at Rr", "DJNZ Rr,", "MOV A, at Rr" };
static int trans2[10] = { 0, -1, -1, 1, -1, -1, -1, -1, 2, 3 };
static int trans3[12] = { 0, 1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5 };
static char *ir[4][6] = {
{ "NOP", "OUTL BUS,A", "INS A,BUS", "IN A,P1", "IN A,P2", "???" },
{ "XCHD A, at R0", "XCHD A, at R1", "???", "OUTL P1,A", "OUTL P2,A", "???" },
{ "MOVX A, at R0", "MOVX A, at R1", "ORL BUS,#", "ORL P1,#", "ORL P2,#", "???" },
{ "MOVX @R0,A", "MOVX @R1,A", "ANL BUS,#", "ANL P1,#", "ANL P2,#", "???" } };
#### END OF TABLES.H ####
echo All done.
More information about the Comp.sources.unix
mailing list