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