[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: anybody got a 65c02 or 65c816 disassembler?



In article <68a2ec1b.0211171226.1e2897a6@posting.google.com>,
Lazarus I. Long <me@lazilong.com> wrote:
>
>all i really need is something equivalent to the Apple II monitor
>disassembler.  simple, stupid and fast.  not interactive, no smarts
>about separating out data from code etc.

Don't have such a beast, but it's conceptually pretty simple to make
a 6502/65C02 disassembler given these specifications. It's a bit more
work to do it for the 65816, but not much more if properly structured.

Basically, have a function that will:

	1. Iterate over each byte of the source data stream for number
	   of bytes that you want to disassemble. This assumes the data
	   stream has already been converted from ASCII to integers
	   in-memory, if necessary. If already done, then no extra work
	   is needed.

	2. Do a hash table lookup for the first byte and determine if
	   valid opcode

	3. If not a valid opcode, try decode next byte in input data stream
	   by incrementing input data pointer by 1 and go back to step 1.

	4. If valid opcode, look up the opcode's info in a table to
	   determine if 0, 1, or 2 data bytes will follow...and also fetch
	   the opcode's ASCII mnemonic from the table

	   (You probably do want to know the starting memory address and
	    increment this as you go along in the iteration because some
	    addressing modes are relative, such as a short branch which
	    might specify that it's for '16 bytes earlier' rather than an
	    absolute address. Ie: '30 E8' is BMI -18; 30 is BMI, and if
	    value is > 80, aka high bit is set, is a negative number. FF
	    minus E8 is 18. So 18 bytes back is target of branch.)

	5. Print the decoded info

	6. Skip the number of data bytes to start with next opcode

	7. Go back to step 1

I'm not sure the best way to design an hash table, but I would probably
do it as something like this:

Allocate an array: opcodeTable[256]

Each position in it represents a corresponding opcode number. For example,
position 0 would be opcode number 0, position 1 would be opcode number 1,
etc.

If it's a valid opcode, set its value to be pointer to address of structure
with data.

If it's invalid opcode, set its value to be NULL.

Then make a struct...something like:

typedef struct
{
	char *	mnemonic;
	int	numDataBytes;
	int	addressingMode;
} opcodeInfo;

Then you could have a routine that allocates memory for each struct, and
fill it out with appropriate values, then update the pointer in opcodeTable
to point to it.

enum
{
	None     = 0,
	Relative = 1,
	Absolute = 2
};

defineOpcode(0x90, "BCC", 1, Relative);

would call a function that allocates memory for a new struct, fill it
out, then stuff the pointer to struct in the 144th entry of the hash table
(0..255, so 0x90 would be 145th position)

For example:

void defineOpcode(int opcode, char *mnemonic, int argCount, int addrMode)
{
	newStruct = malloc(sizeof(struct opcodeInfo));
	newStruct->mnemonic = mnemonic;
	newStruct->numDataBytes = argCount;
	newStruct->addressingMode = addrMode;
	opcodeTable[opcode] = newStruct;
}


defineOpcode(0x20, "JSR", 2, Absolute);

defineOpcode(0xEA, "NOP", 0, None);

If there's an invalid opcode, then easily handled with:

opcodeTable[0xXX] = NULL;

There's a flag bit in the struct to indicate if the opcode's data
(if it has any) should be treated as relative or absolute. That'd help
make decoding easier.

Then the actual main loop checking would be simple...

	inputData is a ptr to the current byte in the input data

	if(opcodeTable[*inputData] != NULL)
	{
		opcodeDataPtr = opcodeTable[inputData];
		opcodeMnemonic = opcodeDataPtr->mnemonic;
		opcodeDataCount = opcodeDataPtr->numDataBytes;
		/* decode stuff, depending on if 0, 1, or 2 data bytes */
		decodeData(inputData, opcodeDataCount);
		/* print decoded info */
		printDecodedInfo(...);
		/* next step will make it skip data bytes and start at */
		/* next opcode to decode */
		inputData += opcodeDataCount;
	}
	else
	{
		/* increment pointer to input data by one and try again */
		/* in next trip around the loop */
		inputData++;
	}

I'm guessing that it's probably an hour's work to make that program.

-Dan

(email sent to original poster as a courtesy and posted to USENET.)