!pr1
Add Smarts to 65816 Dis-Assembler...............Jim Poponoe

I found fascinating the article by Bob Sander-Cederlof in the March 1985 AAL, entitled "A Disassembler for the 65816".  I purchased AAL Quarterly Disk 18 and tried it out for myself, watching 65802 instructions zip before my eyes.

But, whoa!  Bob was correct in warning that his disassembler would not know whether immediate-mode instructions are two or three bytes long.  Bob explained "only by executing the programming, and tracing it line-by-line, can we tell."  A fully accurate disassembler for the 65816 would have to execute the equivalent of STEP and TRACE, following the logic flow of the program.

I wanted an easier, quick-and-dirty way to spiff up the output, one that would at least recognize simple, straightforward changes in the processor status.  I reasoned that:

!lm+9
!pp-4
1)  Interpretation of immediate-mode instructions depends on the state of E, M, and X bits in the status register.

2)  E and C bits are exchangeable.

3)  The disassembler must keep track of all four bits (C, E, X, and M) in order to disassemble immediate mode opcodes correctly.

4)  The disassembler should also keep track of when the processor status is pushed onto or pulled off the stack.

!pp0
!lm-9
My implementation assigns a memory location for the E-bit, and a small "stack" of 8 memory locations for the status register.  One more memory location serves as the stack pointer.  Here is the initialization code for these memory locations, replacing lines 1450-1480 in Bob's March 1985 listing:




    <<<<lines 1450-1486>>>>




I added a JSR TEST.OP.CODES line at 5865, to call some new code which looks for CLC, SEC, REP, SEP, PHP, PLP, and XCE instruc- tions.  It adjusts the flags appropriately in response to these instructions.  If the current opcode is none of the above, TEST.OP.CODES checks the status bits and the opcode to set up the correct immediate-mode length.  If the opcode is an immediate mode operation on the A-register, and if E=0 and M=0, then 16-bit immediate will be disassembled.  If the opcode is an immediate mode operation on the X- or Y-register, and if E=0 and X=0, then 16-bit immediate will be disassembled.  Otherwise, any kind of immediate mode instruction will be disassembled with an 8-bit operand.

I tried the program on all the sample 65802 code I could find, and it was all disassembled correctly.  Of course it is certainly possible to fool my program.  The C-bit, and hence possibly the E-bit, can be changed in many other ways than by using the CLC and SEC instructions.  The program flow is not followed, so it is possible than my emulation of the carry status and the XCE will not agree with what happens in some code.  If you adhere to the "nice" standard of always using explicit SEC or CLC opcodes before an XCE opcode, the disassembler should stay in step perfectly.

When you type 800G to link in the disassembler (refer to Bob's article to know what I mean here) the status is initialized to E=C=M=X=1.  This means normal 6502 mode.  If you disassemble some code with XCE's in it, the status I keep will probably be left in some other mode.  If you then try to disassemble some plain vanilla 6502 code, the immediate instructions may be disassembled with 16-bit operands.  Just type 800G again to get back to normal.

By the way, in working with Bob's disassembler I discovered a typing error in his code.  Line 3980 was originally >OXA TAY, and it should have been >OXA DEY.  The hex listing in Bob's article showed $AF stored in $963; it really should be $89.  Without this change, the DEY opcode disassembles as TAY!

The listing that follows has been extensively modified by Bob, based on my code I sent him last September.  The lines are numbered to follow after the last line of the program on the quarterly disk.





<<<<<listing of lines 7060-7880>>>>

!np







































Further notes by Bob Sander-Cederlof:

Thanks, Jim!  Your ideas were a big help!  In looking back over my work, I noticed some more improvements.

R. F. O'Brien wrote us just this week with the news that he had found two bugs in the disassembler.  One was the typing error at line 3980 which Jim noted above.  But Robert found a second typo, at line 4960.  ">OXB LDX" should be changed to ">OXB CPX".  This changes the byte shown in the original article at $9BF from $19 to $0F.

I found a way to simplify the >ON macro, which speeds up assembly and shortens the listing.  Replace lines 1220-1290 with the following:


<<<<<listing of lines 1220-1290>>>>


I also discovered that one kind of Apple monitor ROM did not have the RELADR subroutine, so I re-coded lines 6760-6950.  Replace those lines with the following:






<<<<listing of lines 6760-6900>>>>>






One last item.  I wrote a test routine to call the disassembler for every possible opcode from 00 to FF.  Here it is:




<<<<listing of lines 7890 to end>>>>
