(* Use MODE 3: ROMAS Disassembler - copyright 1985 TBK Associates __________________________________________________ This is the source code for the 6502 disassembler supplied with the ROMAS cross assembler/macro editor package. It has been provided to show how the ROM may be used to assemble programs and then run them on the BBC microcomputer. The user may freely modify the code to customise it to his own specification, but please respect our copyright. If it is assembled and located into file DIS then the disassembler may be called by using:- *DIS () The disassembler will start from address '' and if the disassembler accesses memory above &8000 it will disassemble the sideways ROM specified as ')'. If the ROM number is not included then BASIC will be disassembled by default. The disassembly will continue until the ESCAPE key is pressed. *) ; First do all the equates for the program. ; Operating system calls: osrdrm equ &ffb9 ; read byte from ROM. osrdch equ &ffe0 ; get key press. osasci equ &ffe3 ; output character expanding . osnewl equ &ffe7 ; output , . oswrch equ &ffee ; output character. osbyte equ &fff4 ; general effects, *FX. ; Zero page workspace, ; Uses locations &70 - &7B: line_ptr equ &70 ; index into command line. first_byte equ &71 ; first byte of current instruction. sec_byte equ &72 ; second byte. third_byte equ &73 ; third byte. length equ &74 ; length of current instruction. x_temp equ &75 ; temporary storage for X register. y_temp equ &76 ; temporary storage for Y register. rom_number equ &77 ; number of required ROM. number equ &78 ; used in calculating hex. numbers. pc_value equ &7A ; address of current instruction. ; Constants: space equ 32 ; ASCII value of space. os_ptr equ &f2 ; pointer to start of command line. os_address equ &f6 ; pointer into ROM for OSRDRM. type 'Assembling ROMAS Disassembler'+chr$(13) type ' (C) 1985 TBK Associates'+chr$(13) proc '6502' ; not really needed. tab 14 ; E.CONFIG got tabs every 14 columns. org &2000 ; select free memory. ; ENTRY point: dis_asm: sty line_ptr ; store index into command line. jsr get_hex ; get start address, stx pc_value ; and store it. sty pc_value+1 ; lda #&bb ; ldx #0 ; get ROM number of BASIC. ldy #&ff ; jsr osbyte ; stx rom_number ; select as ROM for DISASM. jsr get_hex ; get optional ROM number. beq next_dsm ; stx rom_number ; select this ROM for DISASM. next_dsm: jsr print_addr ; print current address. jsr search_code ; find next instruction in tables. jsr print_code ; print mnemonic. jsr do_addr ; print addressing modes. lda #23 ; jsr calc_space ; space out screen. jsr print_bytes ; print hex. bytes of instruction. lda #34 ; jsr calc_space ; more space. ldx #0 ; next_asc: lda first_byte,x ; jsr print_ascii ; print ASCII of hex. bytes. inx ; dec length ; bne next_asc ; jsr osnewl ; bit &ff ; test for ESCAPE key bpl next_dsm ; being pressed. ; continue if not pressed. ; Acknowledge Escape condition. ack_escape: lda #&7e ; acknowledge the jmp osbyte ; ESCAPE condition. ; Calculate number of spaces to print onto screen ; in order to reach column number in A. calc_space: pha ; lda #&86 ; find current column number. jsr osbyte ; stx x_temp ; pla ; calculate number of spaces sec ; to print to get to the sbc x_temp ; required column number. jmp multi_space ; print the spaces. ; Search for opcode in table, if not found then it must be an illegal ; instruction in which case the mnemonic number will select '---'. search_code: jsr read_byte ; get first byte of instruction. sta first_byte ; ldx opcodes ; ldy #0 ; more_ops: cmp opcodes+1,y ; search for it in beq got_op ; the opcode table. iny ; dex ; get index into this table in Y. bne more_ops ; got_op: ldx mnems,y ; get number of this mnemonic. lda addrs,y ; get index into instruction pha ; length table. tay ; lda oplens,y ; get length in bytes. sta length ; ldy #1 ; get_ops: cpy length ; if instruction is longer beq no_extra ; than one byte then get sty y_temp ; extra bytes of instruction. jsr read_byte ; ldy y_temp ; get second and possibly sta first_byte,y ; third bytes. iny ; bne get_ops ; no_extra: pla ; tay ; index into length table in Y. txa ; mnemonic number in X. rts ; ; Print the current mnemonic. print_code: asl a ; stx x_temp ; calculate index sty y_temp ; into mnemonic table adc x_temp ; by multiplying number tax ; by three, result in X. ldy #3 ; all are three letters long. more_mnem: lda mnemonics,x ; jsr oswrch ; print this mnemonic. inx ; dey ; bne more_mnem ; ldy y_temp ; separate mnemonic from its jmp print_space ; operands by one space. ; Print hexadecimal bytes of current instruction. print_bytes: ldy length ; get length of instruction. ldx #0 ; more_cds: lda first_byte,x ; print each byte of jsr print_hex ; instruction in jsr print_space ; hexadecimal and inx ; separate them by dey ; one space. bne more_cds ; rts ; ; Do the addressing modes. do_addr: tya ; get index into addressing asl a ; mode action address table. tax ; lda address+1,x ; get high byte. pha ; lda address,x ; get low byte. pha ; add_0: rts ; execute via stack. add_2: lda #'#' ; immediate mode. jsr oswrch ; add_1: lda sec_byte ; zero page mode. prt_first: pha ; lda #'&' ; print hex. byte p_char: jsr oswrch ; preceeded by the p_hex: pla ; ampersand character. jmp print_hex ; add_3: lda #'A' ; accumulator mode. jmp oswrch ; add_4: lda third_byte ; absolute mode. jsr prt_first ; lda sec_byte ; jmp print_hex ; add_5: jsr left_b ; indexed indirect mode. jsr add_1 ; jsr print_x-3 ; right_b: lda #')' ; print a left bracket. jmp oswrch ; add_6: jsr left_b ; indexed indirect mode. jsr add_1 ; jsr right_b ; jsr comma ; print_y: lda #'Y' ; print Y register. jmp oswrch ; add_7: jsr add_1 ; zero page X mode. jsr comma ; print_x: lda #'X' ; print X register. jmp oswrch ; add_8: jsr add_4 ; absolute X mode. jmp print_x-3 ; add_9: jsr add_4 ; absolute Y mode. jmp print_y-3 ; add_10: jsr left_b ; indirect mode. jsr add_4 ; jmp right_b ; add_11: jsr calc_add ; relative mode. jsr prt_first ; txa ; jmp print_hex ; calc_add: ldx pc_value ; get current address. ldy pc_value+1 ; lda #0 ; sta third_byte ; lda sec_byte ; calculate address clc ; of branch destination bpl pos_rel ; using offset from dec third_byte ; current address. pos_rel: txa ; adc sec_byte ; tax ; tya ; adc third_byte ; tay ; rts ; comma: lda #',' ; print comma. jmp oswrch ; add_12: jsr add_1 ; Zero page Y mode. jsr comma ; jmp print_y ; left_b: lda #'(' ; print left bracket. jmp oswrch ; EXTEND 'DISASM1' ; chain next part of program.