1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
|
;
; Ullrich von Bassewitz, 07.08.1998
;
; unsigned DbgDisAsm (char* buf, unsigned addr);
; unsigned DbgDisAsm (unsigned addr);
;
;
; Part of this code is taken from the Plus/4 machine language monitor
; (TEDMon).
;
.import popax
.import __hextab, OffsetTab, AdrFlagTab
.import SymbolTab1, SymbolTab2, MnemoTab1, MnemoTab2
; -------------------------------------------------------------------------
; Equates for better readability
.importzp sreg, tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3
BufIndex = tmp1 ; Index into output buffer
OperandLen = tmp2 ; Length of operand
BufLen = tmp3 ; Length of output buffer
AdrFlagBuf = tmp4 ; Flag for addressing mode
YSave = sreg ; Temp storage
XSave = sreg+1 ; Dito
BufPtr = ptr1 ; Pointer to output buffer
MemPtr = ptr2 ; Pointer to memory to disassemble
MnemoBuf = ptr3 ; Buffer for decoding mnemonic
; -------------------------------------------------------------------------
; Main entries
.export _DbgDisAsm, _DbgDisAsmLen
.proc _DbgDisAsm
sta BufLen ; Save the buffer length
jsr popax ; Get the buffer pointer
sta BufPtr
stx BufPtr+1
jsr popax ; Get the address
sta MemPtr
stx MemPtr+1
lda #0
sta BufIndex ; Initialize index into buffer
jsr DisAssLine ; Disassemble one line into the buffer
lda BufLen ; Get requested length
sec
sbc BufIndex
beq L2
tax ; Count into X
ldy BufIndex
lda #$20 ; Get a space
L1: sta (BufPtr),y
iny
dex
bne L1
L2: lda #0 ; Add C string terminator
sta (BufPtr),y
beq disassret
.endproc
_DbgDisAsmLen:
sta MemPtr ; Save address
stx MemPtr+1
ldy #$00
lda (MemPtr),y ; Get the opcode from memory...
jsr AnalyzeOPCode ; ...and analyze it
disassret:
ldx OperandLen ; Get length of operand
inx ; Adjust for opcode byte
txa
ldx #$00 ; Clear high byte
rts
; -------------------------------------------------------------------------
; Helper functions
Put3Spaces:
jsr PutSpace
Put2Spaces:
jsr PutSpace
PutSpace:
lda #$20
PutChar:
sty YSave ; Save Y
ldy BufIndex ; Get current line pointer
cpy BufLen ; Be sure not to overflow the buffer
bcs PC9
sta (BufPtr),y ; store character
iny ; bump index
sty BufIndex
PC9: ldy YSave ; get old value
rts
; Print the 16 bit hex value in X/Y
PutHex16:
txa
jsr PutHex8
tya
; Print 8 bit value in A, save X and Y
PutHex8:
stx XSave
sty YSave
ldy BufIndex
pha
lsr a
lsr a
lsr a
lsr a
tax
lda __hextab,x
sta (BufPtr),y
iny
pla
and #$0F
tax
lda __hextab,x
sta (BufPtr),y
iny
sty BufIndex
ldy YSave
ldx XSave
rts
; -------------------------------------------------------------------------
; Disassemble one line
DisAssLine:
ldy MemPtr
ldx MemPtr+1
jsr PutHex16 ; Print the address
jsr Put2Spaces ; Add some space
ldy #$00
lda (MemPtr),y ; Get the opcode from memory...
jsr AnalyzeOPCode ; ...and analyze it
pha ; Save mnemonic
ldx OperandLen ; Number of bytes
; Print the bytes that make up the instruction
inx
L2083: dex
bpl L208C ; Print the instruction bytes
jsr Put3Spaces ; If none left, print spaces instead
jmp L2094
L208C: lda (MemPtr),y ; Get a byte from memory
jsr PutHex8 ; ...and print it
jsr PutSpace ; Add some space
L2094: iny ; Next one...
cpy #$03 ; Maximum is three
bcc L2083 ;
jsr Put2Spaces ; Add some space after bytes
; Print the assembler mnemonic
pla ; Get mnemonic code
ldx #$03
jsr PutMnemo ; Print the mnemonic
ldx #$06
; Print the operand
L20A4: cpx #$03
bne L20BA
ldy OperandLen
beq L20BA
L20AC: lda AdrFlagBuf
cmp #$E8 ; Branch?
lda (MemPtr),y ; Get branch offset
bcs GetBranchAdr ; If branch: Calculate address
jsr PutHex8 ; Otherwise print 8bit value
dey
bne L20AC
L20BA: asl AdrFlagBuf
bcc L20CC
lda SymbolTab1-1,x
jsr PutChar
lda SymbolTab2-1,x
beq L20CC
jsr PutChar
L20CC: dex
bne L20A4
rts
; If the instruction is a branch, calculate the absolute address of the
; branch target and print it.
GetBranchAdr:
jsr L20DD
clc
adc #$01
bne L20D9
inx ; Bump high byte
L20D9: tay
jmp PutHex16 ; Output address
L20DD: ldx MemPtr+1
tay
bpl L20E3
dex
L20E3: adc MemPtr
bcc L20E8
inx ; Bump high byte
L20E8: rts
; -------------------------------------------------------------------------
; Subroutine to analyze an opcode byte in A. Will return a byte that
; encodes the mnemonic, and will set the number of bytes needed for this
; instruction in OperandLen
AnalyzeOPCode:
tay
lsr a
bcc L20F8
lsr a
bcs L2107
cmp #$22
beq L2107
and #$07
ora #$80
L20F8: lsr a
tax
lda OffsetTab,x
bcs L2103
lsr a
lsr a
lsr a
lsr a
L2103: and #$0F
bne L210B
L2107: ldy #$80
lda #$00
L210B: tax
lda AdrFlagTab,x
sta AdrFlagBuf
and #$03
sta OperandLen
tya
and #$8F
tax
tya
ldy #$03
cpx #$8A
beq L212B
L2120: lsr a
bcc L212B
lsr a
L2124: lsr a
ora #$20
dey
bne L2124
iny
L212B: dey
bne L2120
rts
; -------------------------------------------------------------------------
; Print the mnemonic with code in A (that code was returned by
; AnalyzeOpcode).
PutMnemo:
tay
lda MnemoTab1,y
sta MnemoBuf
lda MnemoTab2,y
sta MnemoBuf+1
L213A: lda #$00
ldy #$05 ; 3*5 bits in two bytes
L213E: asl MnemoBuf+1
rol MnemoBuf
rol a
dey
bne L213E
adc #$3F
jsr PutChar
dex
bne L213A
jmp PutSpace
|