***++++++++++++++++++++++++++++++*** !HEXDATA set 11*2 ;1 \ Pushed onto the stack !OPERANDS set 38*2 ;2 > in this order. !INSTRUCT set -15*2 ;3 / !LINELEN set 42*2 ;offset: 0 11 34 49 *-+-* ;screen:
!OPE_INDENT set 16*2 ; ***++++++++++++++++++++++++++++++*** !BC set $12 !BH set $1D !HM set $3D !ADDR_COL set $03 !HEX_COLA set $04 !HEX_COLB set $05 !INS_COL set $06 !BYTE_COL set $07 !WORD_COL set $08 !DWORD_COL set $09 !REG_COL set $0A !IMD_COL set $0B !ADD_COL set $0C !HIGH_COL set $0E ***++++++++++++++++++++++++++++++*** !PROG_ILL set $03 !PROG_PAWS set $02 !PROG_DONE set $01 !PROG_NONE set $00 !PMASK set $30 ***++++++++++++++++++++++++++++++*** !MAX_BREAK set 12 ***++++++++++++++++++++++++++++++*** !GETINST set 3 ***++++++++++++++++++++++++++++++*** !SCREENPOS set 0 !DX_START set 160 !DY_START set 0 !NUM_LINES set 23 !NUM_CHARS set 22 !TOTALCHARS set !NUM_LINES * !NUM_CHARS !CODELEN set ProgEnd - CodeStart / 16 ***************************************************************************** * This is the program header information:- * * Compile as .COM and move the result to a .EXE file. * ***************************************************************************** ORG 0 HEADER ***************************************************************************** * MonPC V1.00 (C) Matthew Judge 1996 * ***************************************************************************** CodeStart: push.w #Prog_Exit ;Our ultimate destination. cs:move.w es, PSPSegment ;Save the PSP segment move.w cs, bx ;Save the CODE segment. cs:move.w bx, CodeSegment ;Done. move.w bx, ds ;Set DS to match CS. move.w #MEM_ERROR, dx ;The memory error string. move.b #$4a, ah ;Give memory back. cs:sub.w PSPSegment, bx ;Get the Code segment. add.w #!CODELEN, bx ;Add the length of the code. trap #$21 ;Get DOS to sort it all out. bcs.s Dos_Print ;Exit if error. move.b #$48, ah ;Allocate memory for program screen. move.w #$1000, bx ;The amount to allocate. trap #$21 ;DOS call. bcs.s Dos_Print ;Exit if error. cs:move.w ax, ProgScreen+2 ;Success - Save it. bsr.w GetCPUID ;Get the CPU identity. move.w #CPU_ERROR, dx ;Prepare the error message. cmp.b #'2', CPUIdent ;Check if the CPU is up to the job. blt.s Dos_Print ;Less than 386 and quit. bsr.w Get_Arguements ;Get the command line arguements. or.b ah, ah ;Check if we have a filename. beq.s _No_FileName ;Nope. bsr.w Load_EXE ;Load the executable file. bcs.s _Load_Error ;File name invalid. _No_FileName: move.b #$52, ah ;The DOS call. trap #$21 ;Get the INVARS. es:move.w -2(bx), ax ;Get the first PSP segment. cs:move.w ax, FirstMCB ;Save it. cs:move.w ax, StartMCB ;Set it as the first MCB to view. bsr.w _Set_Vectors ;Hook the interrupts! bsr.w Prog_Loop bra.w _Reset_Vectors _Load_Error: move.w #EXE_ERROR, dx ;The error message. bsr.w Dos_Print move.w #Filename, dx Dos_Print: move.b #9, ah trap #$21 rts ***************************************************************************** _Set_Vectors: move.w #VectorTable, bx ;The list of vectors to change. _Set_V_Loop: cs:lfs (bx), di ;Get the address of the vector. cs:move.w 4(bx), si ;Where to save it. fs:push.l (di) ;Get the old vector. cs:pop.l (si) ;Save it. push.w cs ;Push the code segment. cs:push.w 6(bx) ;Push the new handler. fs:pop.l (di) ;Set the new handler. lea 8(bx), bx cs:cmp.w #-1, (bx) bne.s _Set_V_Loop rts ***************************************************************************** _Reset_Vectors: move.w #VectorTable, bx ;The list of vectors to change. _Reset_V_Loop: cs:lfs (bx), di ;Get the address of the vector. cs:move.w 4(bx), si ;Where to restore it from. cs:push.l (si) ;Get the old vector. fs:pop.l (di) ;Save it. lea 8(bx), bx cs:cmp.w #-1, (bx) bne.s _Reset_V_Loop rts ***************************************************************************** Prog_Loop: bsr.w _Save_MainScreen ;Save the program screen _P_Loop1: bsr.w Update_Bars ;Show the text on the bars. _P_Loop2: bsr.w CodDisplay ;Dissassemble from address PQ1: bsr.w Get_KeyStroke ;Get Keyboard status. or.w ax, ax ;Check if anything has been pressed. beq.s _P_Loop2 ;No, if zero. cmp.w #$011B, ax ;Check for . beq.s _P_Loop_Exit ;Exit if true. move.w #DissRoutine, si ;The list of routines. PQ2: _GetCom_Lp: cs:cmp.b #$FF, (si) ;Check if match high byte only - bne.s _Check_All ;Or match all. cs:cmp.b ah, 1(si) ;Match the high byte only. bra.s _Do_Cmp ;Skip next comparison. _Check_All: cs:cmp.w ax, (si) ;Compare AX with current instruction. _Do_Cmp: bne.s _Move_Next ;Move to next if no match. push #_P_Loop2 ;Return here. cs:bra.w 2(si) ;We have a match - Jump to it. _Move_Next: lea 6(si), si ;Move next. cs:cmp.w #0, (si) ;End of the line? bne.s _GetCom_Lp ;Go again. cmp.w #LastKey, si ;Are we on the second list? beq.s _P_Loop2 ;Yes, quit whilst we are ahead. move.w #SharedKeys, si ;Set SI to the list of shared keys. bra.w _GetCom_Lp ;Go again... _P_Loop_Exit: bra.w _Show_MainScreen ;Restore the program screen ***************************************************************************** _Save_MainScreen: bsr.w _Save_Palette ;Save the colours. cs:lds TargetData, di cs:les ProgScreen, si move.w #$3e80, cx repne:movs.l ***************************************************************************** * Set up the work screen: Colour bars across the top an bottom * ***************************************************************************** _Show_ProgScreen: move.w #PALETTE, si ;The palette. bsr.w _Set_Palette cs:les TargetData, di ;Where to print. move.w #40, cx ;The count. dc.b $66,$B8,$20,!BC,$20,!BC ;Set AX with our fill colour. repne:stos.l ;Repeat not equal - stosd. move.w #!NUM_LINES*40, cx ;The number of Lines to clear dc.b $66 eor.w ax, ax ;Clear EAX dc.b $66,$F2,$AB ;Repeat not equal. move.w #40, cx ;The count. dc.b $66,$B8,$20,!BC,$20,!BC ;Set AX with our fill colour. dc.b $66,$F2,$AB ;Repeat not equal - stosd. rts ***************************************************************************** _Show_MainScreen: move.w #SPALETTE, si ;The saved palette. bsr.w _Set_Palette ;Restore the palette. cs:les TargetData, di ; cs:lds ProgScreen, si ; move.w #$3e80, cx ; dc.b $66,$F2,$A5 ;Repeat not equal - movsd. rts ***************************************************************************** * SI = The source address * * DS = The source segment * * DI = The target address * * ES = The target segment * * CS = The code segment * * CL = The number of lines to print * ***************************************************************************** CodDisplay: bsr.w Wait_Trace ;Stop nasty flickering. eor.w bp, bp ;Clear BP cs:les TargetData, di cs:lds CodSource, si ;Where to dissassemble from. move.w #!NUM_LINES, cx ;The count of lines. _Diss_Loop: lea 160(di), di ;Move to the next line. push cx ;Save the count. push di ;Save the target postion. push.w #_Ret_ ;The return address. bsr.w CLS_Line ;Clear the line. ******* cs:move.w di, ax ;Our work register. add.w #!HEXDATA, ax push ax ;Where our our hex is printed. push.w #MPrint_Hex ;Print hex value first. _HexRoutine: ******* push si ;The address to dissassemble. add.w #!OPERANDS, ax _OperSet: push ax ;Where our operands are printed. add.w #!INSTRUCT, ax _InstSet: push ax ;Where our instructions are printed. ******* push.w #Get_Instruction ; cs:cmp.w cx, CursorLine ;Is this the cursor position? bne.s _Print_Address ;No - Just print the address. cs:move.w si, CursorPos ;Set the address. pop ax ;Dump AX. push.w #Print_Arrow ;Yes, print an arrow. ******* _Print_Address: cs:move.b AddrCol, ah ; move.w ds, bx ; move.b #4, cl ; Print bsr.w Print_Hex ; the memory segment bsr.w Print_Colon1 ; and address of the current cs:move.b AddrCol, ah ; move.w si, bx ; dissassembled area. move.b #4, cl ; bra.w Print_Hex ; _Ret_: pop di pop cx ;Restore the line count. dbra _Diss_Loop cs:move.w si, NextPage ;Save for page down. cs:cmp.w #!OPE_INDENT, _OperSet-2 ;Check if we are showing the beq.w PrintRegisters ;Display the programs registers. rts ***************************************************************************** Print_Arrow: cs:move.b InstCol, ah ;Print an arrow. move.b #'-', al ; es:move.w ax, (di) :Print it. move.b #26, al ;Print an arrow. es:move.w ax, 2(di) ;Print it. Get_Instruction: cs:move.b #!GETINST, Debug ;Flag that we are dissassembling. lea 4(di), di ;The screen position. cs:move.w #1, Size ;The size in bytes of the instruction. cs:move.b #2, W_Size ;The size in bytes of a word. cs:move.w #W_AX, DReg ;The register type - AX / EAX. Prefix_Start: move.w #InstData, bx ; FData_Start: lods.b ;Get the first word. move.b al, ch ds:move.b (si), cl and.w #$FF, ax ;Mask it off. shl.w #2, ax ;multiply by 4. add ax, bx ;Where we want to go. cs:bra.w (bx) ;* ***************************************************************************** Force_W_Op2: dc.b $0F,$BA,$E9,$08 ;Set bit 8 to force word operation. Reg_Op2: cs:inc.b Size pop di ;Where to print the instruction name. move.b ch, al ; and.b #$FE, al ; cmp.b #$C6, al ; bne.s _Do_List ; push #_Name_Done ; bra.w P_2BX_Str ; _Do_List: bsr.w P_BX_List _Name_Done: btst #8, cx ;Check for byte or word. bcs.s Op2_Word ;Word instruction. bsr.w Print_DotB ;Byte instruction. bra.s Op2_SDone ; Op2_Word: bsr.w Print_DotWD ; Op2_SDone: pop di ;Where to print the operands... pop si ;The dissassembly address. move.b ch, al and.b #$FE, al cmp.b #$FE, al beq.s _No_Prefix cmp.b #$F6, al bne.w _Do_Prefix ds:move.b 1(si), al and.b #%111000, al or.b al, al beq.w _Do_Prefix _No_Prefix: bra.w Print_BX_SI ***************************************************************************** I_SRC_D_Op: cs:inc.b Size ;Inst:- Immediate/Source/Destination. pop di ;Get the instruction start address. bsr.w P_2BX_Str bsr.w Print_DotWD pop di ;exchange removed. pop si bsr.w Get_Prefix_Data dc.b $0F,$BA,$E9,$09 ;BTS push cx bcc.s _I_Word cs:inc.b Size bsr.w Print_I_Byte bra.s _I_Set _I_Word: bsr.w Print_I_DWord cs:move.b W_Size, ah cs:add.b ah, Size _I_Set: cs:move.w #Right_Word_Reg-_AR1, _AR1-2 pop cx push #Print_Rot2 push #_I_Jump2 bra.w Print_Comma ***************************************************************************** Reg_Imd_Op: pop di bsr.w P_2BX_Str ;Print the command name. cs:move.w #Right_Reg_Set1-_AR2, _AR2-2 btst #11, cx ;Test the relevant bit. bra.s Reg_Imd_Jmp ;Go and process it. ***************************************************************************** AX_Imd_Op: pop di ;Pop where to print the command. bsr.w P_2BX_Str ;Print the command name. cs:move.w #Print_Reg-_AR2, _AR2-2 ;The second arguement is a register. btst.w #8, cx ;Check size of instruction. Reg_Imd_Jmp: push #Print_Rot1 ;Where to jump to. bcs.s _RI_Word ;Word intruction. cs:inc.b Size cs:move.w #Print_I_Byte-_AR1, _AR1-2 move.w #D_AL, dx bra.w Print_DotB _RI_Word: cs:move.b W_Size, ah cs:add.b ah, Size cs:move.w #Print_I_DWord-_AR1, _AR1-2 cs:move.w DReg, dx bra.w Print_DotWD ***************************************************************************** AX_Add_Op: pop di bsr.w P_2BX_Str btst #9, cx ;Check direction. bcs.s _Add_AX :Address followed by AX. cs:move.w #Print_Address-_AR1, _AR1-2 cs:move.w #Print_Reg-_AR2, _AR2-2 bra.s _Dir_Set _Add_AX: cs:move.w #Print_Reg-_AR1, _AR1-2 cs:move.w #Print_Address-_AR2, _AR2-2 _Dir_Set: cs:add.b #2, Size ;Set the size. push #Print_Rot1 ;The routine to display the data. cs:move.w DReg, dx ;Set it as something btst #8, cx ;Check the size. bcs.w Print_DotWD ;Print .W or .D extension. move.w #D_AL, dx ;Set it as something else. bra.w Print_DotB ;Print .B extension. ***************************************************************************** Gen_Reg_Tog: dc.b $0F,$BA,$F9,$09 bra.s Gen_Reg *-+-+-+-* Gen_Reg_Ip: dc.b $0F,$BA,$E9,$09 ;Set bit 9 to force direction. *-+-+-+-* Gen_Reg_Iw: dc.b $0F,$BA,$E9,$08 ;Set bit 8 to force Size. *-+-+-+-* Gen_Reg: cs:inc.b Size pop di ;Get the instruction start address. bsr.w P_2BX_Str push #_I_Jump1 btst #8, cx ;Word or byte. bcs.s Gen_Reg_Word cs:move.w #Left_Reg-_AR1, _AR1-2 bra.w Print_DotB Gen_Reg_Word: cs:move.w #Left_Reg-_AR1, _AR1-2 bra.w Print_DotWD _I_Jump1: push #Print_Rot1 ;Where to Jump to. _I_Jump2: btst #14, cx ; bcs.s _RR_BP _I_Jump3: btst #9, cx ;Check direction. bcs.s _RR_BP _BP_RR: cs:move.w #Print_BX_SI-_AR2, _AR2-2 rts _RR_BP: cs:move.w _AR1-2, ax sub.w #_AR2-_AR1, ax cs:move.w ax, _AR2-2 cs:move.w #Print_BX_SI-_AR1, _AR1-2 rts ***************************************************************************** Print_Rot1: pop di ;Pop the operand print address. pop si ;Pop the dissassembly address. Print_Rot2: dc.b $66 ds:move.w 1(si), bx ;Our byte/word/D-Word data. push bx ;Save BX - Just in case. bsr.w Dummy ;Whatever. _AR1: bsr.w Print_Comma ;The divider. pop bx ;Restore BX. bra.w Dummy ;Whatever - aswell. _AR2: ***************************************************************************** CL1_BX_Op: cs:move.b #2, Size ;CL/CX/1 Prefix. pop di ;Where to print the instruction name. bsr.w P_BX_List *-+-+-* btst #8, cx ;Word or byte. bcs.s CX_Word bsr.w Print_DotB bra.s CX_Set CX_Word: bsr.w Print_DotWD *-+-+-* CX_Set: pop di ;Where to print the operand. pop si ;The dissassembly address. push cx ; btst #9, cx ; bcs.s CX_A ; move.b #1, bl ; Print push #CX_B ; byte bra.w Print_I_Byte ; register CX_A: move.w #D_CL, dx ; Print bsr.w Print_Reg ; CL register. CX_B: bsr.w Print_Comma pop cx bra.w Print_BX_SI ***************************************************************************** _Do_Prefix: push cx bsr.w Get_Prefix_Data ;Find out where our data is. btst #8, cx ;Word or Byte? bcc.s _Prefix_Byte move.b ch, al ; and.b #$FE, al cmp.b #$C0, al beq.s _Prefix_Byte and.b #$6, al cmp.b #$6, al beq.s _Prefix_Word or.b al, al bne.s _Prefix_Byte _Prefix_Word: cs:move.b W_Size, ah cs:add.b ah, Size push #_Prefix_Set bra.w Print_I_DWord _Prefix_Byte: cs:add.b #1, Size bsr.w Print_I_Byte _Prefix_Set: bsr.w Print_Comma pop cx bra.w Print_BX_SI ***************************************************************************** AX_Reg_Op: pop di ;Get the instruction start address. bsr.w P_2BX_Str bsr.w Print_DotWD ; pop di cs:move.w DReg, dx bsr.w Print_Reg bsr.w Print_Comma bra.s Set_Op1 ***************************************************************************** Word_Reg_Op: pop di ;Get the instruction start address. bsr.w P_2BX_Str bsr.w Print_DotWD ; pop di ;Get the operands start address. Set_Op1: pop si ;The dissassembly address. bra.w Right_Word_Reg ***************************************************************************** BX_SI_Flop: pop di bsr.w P_BX_List bra.s BX_SI_jmp *-+-+-* BX_SI_Op: pop di ;Get the instruction start address. bsr.w P_2BX_Str BX_SI_jmp: bsr.w Print_DotWD cs:move.b #2, Size pop di pop si bra.w Print_BX_SI ***************************************************************************** Print_BX_SI: move.b cl, al ; and.w #%111, ax ;Mask off the register bits. shl.b #2, al ;AX * 4 to get offset. move.b cl, bl ;Check for Test Instruction. dc.b $80,$E3,$C0 ;AND BL/$C0 dc.b $80,$FB,$C0 ;CMP BL/$CO beq.w Right_Reg ; dc.b $2E,$0F,$BA,$26 ;Check if 32 Bit registers. dc.w Prefix ;Where to check. dc.b $03 ;Bit 1000. bcc.s _Not_32BX_SI ;No. *++++++++++++++++++++++++++++++++++++++++* P_32BX_SI: cmp.b #%10000, al bne.s _Not_Byte rts _Not_Byte: cmp.b #%10100, al bne.s _Not_DWord cs:add.b #4, Size dc.b $66 ds:move.w 2(si), bx move.b #8, cl bra.w Print_DAddress _Not_DWord: move.w #E_AX, dx add.w ax, dx bsr.w Print_LBracket bsr.w Print_Reg bra.w Print_RBracket *++++++++++++++++++++++++++++++++++++++++* _Not_32BX_SI: or.b bl, bl ; ----------------- bne.s _Do_Imed ; Check for move.b cl, bl ; and.b #7, bl ; immediate data. cmp.b #6, bl ; ----------------- bne.s _BX_SI_Index ; No immediate offset. cs:add.b #2, Size ; ds:move.w 2(si), bx ; bra.w Print_Address ; _Do_Imed: push ax ; btst #7, cx ; bcs.s _Word_Data ; cs:add.b #1, Size ; ds:move.b 2(si), al ; cbw ; xchg.w ax, bx ; bra.s _BX_S_Set ; _Word_Data: cs:add.b #2, Size ; ds:move.w 2(si), bx ; _BX_S_Set: bsr.w Print_Address ; pop ax ; *---------------------------------------- _BX_SI_Index: push si ;Save the dissassembly address. move.w #ILIST3, si add.w ax, si bsr.w Print_LBracket cs:move.w (si), dx bsr.w Print_Reg cs:cmp.w #0, 2(si) beq.s _Index_RBracket bsr.w Print_Comma cs:move.w 2(si), dx bsr.w Print_Reg _Index_RBracket: pop si bra.w Print_RBracket ***************************************************************************** Left_Reg: inc.w bp ; btst #8, cx ; = 11xxxxxx bcs.s Left_Word_Reg ; Left_Byte_Reg: move.w #D_AL, dx bra.s Left_Reg_Set1 Left_Word_Reg: cs:move.w DReg, dx Left_Reg_Set1: ds:move.b (bp,si), bl Left_Reg_Set2: and.w #$38, bx shr.b #1, bl bra.s Add_BX_Reg *-* Right_Reg: inc.w bp ; btst #8, cx ; = 11xxxxxx bcs.s Right_Word_Reg ; Right_Byte_Reg: move.w #D_AL, dx bra.s Right_Reg_Set1 Right_Word_Reg: cs:move.w DReg, dx Right_Reg_Set1: ds:move.b (bp,si), bl Right_Reg_Set2: and.w #%111, bx shl.b #2, bl Add_BX_Reg: add.w bx, dx *-* Print_Reg: eor.w bp, bp cs:move.b RegCol, ah bra.w Print_String ***************************************************************************** Get_Prefix_Data: move.b #2, bl ;Where to get the data move.b cl, bh ; dc.b $80,$E7,$C0 ;AND BH/$C0 dc.b $80,$FF,$C0 ;CMP BH/$CO beq.s _Pre_Set ;Check for word/double word. btst.w #6, cx ;Check for Byte offset. bcs.s _Pre_Byte ; btst.w #7, cx ;Check for Word offset. bcs.s _Pre_Word ;We have a register operand. move.b cl, bh dc.b $80,$E7,$07 ;AND BH/$07 dc.b $80,$FF,$06 ;CMP BH/$06 bne.s _Pre_Set ;All done... _Pre_Word: cs:add.b W_Size, bl ;Add the size of the prefix. bra.s _Pre_Set ;All done. _Pre_Byte: inc.b bl ;Set the size of a Byte. _Pre_Set: eor.b bh, bh ;Clear BH. dc.b $66 ds:move.w (bx,si), bx ;Get the Data. rts ***************************************************************************** Set_Prefix: pop di ;Where to print the prefix. move.b ch, al ; and.b #$FE, al ; Check for 32 bit prefix. cmp.b #$66, al ; bne.s _Normal_Prefix ; ******** _32Bit_Prefix: cmp.b #$67, ch beq.s _32_Address _32_Register: dc.b $2E,$0F,$BA,$2E ;Test and set the bit associated dc.w Prefix ;with this type of prefix. dc.b $00 ;The bit number. bcs.s Dump_Prefix ; cs:move.w #E_AX, DReg ; cs:move.b #4, W_Size ;The size of a word. bra.s _Prefix_Jmp ******** _32_Address: dc.b $2E,$0F,$BA,$2E ;Test and set the bit associated dc.w Prefix ;with this type of prefix. dc.b $03 ;The bit number. bcs.s Dump_Prefix ; copies. bra.s _Prefix_Jmp ; ******** _Normal_Prefix: cs:move.b Prefix, ah ;Save old setting. btst #7, ax ;Check for type of prefix. bcc.s _Segment_Prefix ;Segment prefix. dc.b $2E,$0F,$BA,$2E ;Test and set the bit associated dc.w Prefix ;with this type of prefix. dc.b $01 ;The bit number. bcs.s Dump_Prefix ; bra.s _Print_Prefix ******** _Segment_Prefix: dc.b $2E,$0F,$BA,$2E ;Test and set the bit associated dc.w Prefix ;with this type of prefix. dc.b $02 ;The bit number. bcs.s Dump_Prefix ;Dump multiple copies. ******** _Print_Prefix: and.b #6, ah ;Mask off the visible bits. or.b ah, ah ;Do we have a prefix already there. bne.s _Skip_Indent ;Yep, we do... sub.w #2, di ;Indent a prefixed command. _Skip_Indent: bsr.w P_2BX_Str bsr.w Print_Colon1 ******** _Prefix_Jmp: push di ;Reset the stack. push sp ; pop bx ;Access the stack. ss:move.w 4(bx), si ; ss:inc.w 4(bx) ; ss:move.w 8(bx), di ; ss:add.w #4, 8(bx) ; push.w #Prefix_Start ; push.w di ; cs:push.w _HexRoutine-2 ; rts ; ******** Dump_Prefix: add.w #2, sp ;Dump the stack - Who wanted it? cs:move.b InstCol, ah ;The colour. move.w #D_Q, dx ;Print a query - What is going on? bsr.w Print_String pop si ;Restore the dissassembly address. add.w #4, sp ;Dump this too. rts ***************************************************************************** WD_No_Op: dc.b $0F,$BA,$E9,$08 ;Set bit 8 to force word operation. BWD_No_Op: pop di ;Get the instruction start address. bsr.w P_2BX_Str add.w #2, sp ;Adjust the stack. pop si btst #8, cx ; bcs.s No_Op_Word bra.w Print_DotB No_Op_Word: bra.w Print_DotWD ***************************************************************************** DByte_Op: cs:inc.b Size Byte_Op: pop di ;Get the instruction start address. pop ax ;Dump this... pop si ;Save this... bra.w P_2BX_Str ;Execute this... ***************************************************************************** Enter_Op: cs:move.b #4, Size pop di bsr.w P_2BX_Str pop di pop si ds:move.w 1(si), bx bsr.w Print_I_Word bsr.w Print_Comma ds:move.b 2(si), bl bra.w Print_I_Byte ***************************************************************************** BAdd_Op: cs:move.b #2, Size pop di ;Get the instruction start address. bsr.w P_2BX_Str cs:move.b ByteCol, ah move.b #'.', al stos.w move.b #'S', al stos.w pop di ;Get the operand print address. pop si ;The diss. address. ds:move.b 1(si), al ;Get the byte. cbw ; add.w #2, ax ; move.w si, bx ; add.w ax, bx ; bra.s Print_Address ***************************************************************************** WAdd_Op: cs:move.b #3, Size pop di ;Get the instruction start address. bsr.w P_2BX_Str bsr.w Print_DotW pop di ;Get the operand print address. pop si ;The diss. address. ds:move.w 1(si), ax ;Get the byte. add.w #3, ax ; move.w si, bx ; add.w ax, bx ; Print_Address: move.b #4, cl Print_DAddress: cs:move.b AddCol, ah move.b #'$', al stos.w bra.w Print_Hex ***************************************************************************** CMOV_Op: cs:inc.b Size pop di ;Get the instruction start address. bsr.w P_2BX_Str move.b ch, bl ;Get our data. and.w #$0F, bx ;Mask the relevant bits off. shl.w #2, bx ;Move to the relevant data. move.w #D_JO+1, dx ;The data. add.w bx, dx ;Our offset. push #_I_Jump1 ; push #Gen_Reg_Word ; bra.w Print_String ;Print it. ***************************************************************************** SET_Op: cs:inc.b Size pop di ;Get the instruction start address. bsr.w P_2BX_Str move.b ch, bl ;Get our data. and.w #$0F, bx ;Mask the relevant bits off. shl.w #2, bx ;Shift to the correct offset. move.w #D_JO+1, dx ;The data. add.w bx, dx ;Our offset. bsr.w Print_String ;Print it. bsr.w Print_DotB ; dc.b $0F,$BA,$F1,$09 ;Force byte operation. pop.w di ;Get the operands print address. pop.w si ;Get the Memory address. bra.w Print_BX_SI ;Print it. ***************************************************************************** PushPop_Seg: push bx pop si move.w #D_PUSH, dx ;Preload DX with PUSH... btst.w #8, cx ;Check if it is PUSH. bcc.s _Seg_Push ;Yes. move.w #D_POP, dx ;No, so load it with pop. _Seg_Push: pop di ;Where to print it. cs:move.b InstCol, ah bsr.w Print_String bsr.w Print_DotW ; pop di ;Get the operand print address. cs:move.w 2(si), dx ;Get the operand. pop si bra.w Print_Reg ;Print it. ***************************************************************************** BImd_Op: cs:move.b #2, Size pop di ;Get the instruction start address. bsr.w P_2BX_Str pop di pop si ds:move.b 1(si), bl bra.w Print_I_Byte ***************************************************************************** WImd_Op: cs:move.b #3, Size pop di ;Get the instruction start address. bsr.w P_2BX_Str pop di pop si ds:move.w 1(si), bx bra.w Print_I_Word ***************************************************************************** WDImd_Op: pop di ;Get the instruction start address. bsr.w P_2BX_Str bsr.w Print_DotWD ;It will always be a word. pop di ;Get the operand print address. pop si ;The diss. address. btst.w #9, cx ;Byte or word. bcs.s BWImd_Byte dc.b $66 ds:move.w 1(si), bx cs:move.b W_Size, dh cs:add.b dh, Size bra.w Print_I_DWord BWImd_Byte: ds:move.b 1(si), bl cs:inc.b Size bra.w Print_I_Byte MPrint_Hex: pop di cs:move.b HexColB, ah cs:move.b Size, ch MPrint_lp: lods.b move.b al, bl move.b #2, cl cs:move.b HexColB, ah es:cmp.b ah, -3(di) bne.s _MP_CC cs:move.b HexColA, ah ;The colour _MP_CC: bsr.w Print_Hex dec.b ch bne.s MPrint_lp cs:move.b #0, Debug ;Clear our flags. rts ***************************************************************************** Print_DotWD: dc.b $2E,$0F,$BA,$26 ;BTEST for word or double word. dc.w Prefix ; dc.b $00 ; bcc.s Print_DotW ; Print_DotD: cs:move.b DWordCol, ah move.b #'.', al stos.w move.b #'L', al stos.w rts Print_DotW: cs:move.b WordCol, ah move.b #'.', al stos.w move.b #'W', al stos.w rts Print_DotB: cs:move.b ByteCol, ah move.b #'.', al stos.w move.b #'B', al stos.w rts Print_Hash: cs:move.b InstCol, ah move.b #'#', al stos.w rts Print_LBracket: cs:move.b InstCol, ah move.b #'(', al stos.w rts Print_RBracket: cs:move.b InstCol, ah move.b #')', al stos.w rts Print_Comma: cs:move.b InstCol, ah move.b #$2c, al stos.w rts Print_Colon1: cs:move.b InstCol, ah Print_Colon2: move.b #':', al stos.w rts ***************************************************************************** CSAdd_Op: cs:move.b #3, Size ;Set the initial size. pop di ;Where to print the instruction. bsr.w P_2BX_Str ;Go print it. pop di ;Where to print the operands. pop si ;The dissassembly offset. eor.b bh, bh ;Clear the hight byte. cs:move.b W_Size, bl ;Get the size of the suffix. ds:move.w 1(bx,si), bx ;Get the segment. bsr.w Print_Address ;Print it. bsr.w Print_Colon1 ; dc.b $66 ds:move.w 1(si), bx ;Get the offset. cs:move.b W_Size, cl ;Get the count. cs:add.b cl, Size ;Adjust the size of the instruction. shl.b #1, cl ; bra.w Print_DAddress ;Print it. ***************************************************************************** Seg_Op: cs:inc.b Size pop di bsr.w P_2BX_Str bsr.w Print_DotW pop di ;Where to print the operands. pop si ;Save the segment dc.b $0F,$BA,$E9,$08 ;Set bit 8 to force Size. btst #9, cx ;Check direction. bcc.s Seg_Ip_Op bsr.w Print_BX_SI ; bsr.w Print_Comma ds:move.b 1(si), bl move.w #W_ES, dx bra.w Left_Reg_Set2 ***************************************************************************** Seg_Ip_Op: ds:move.b 1(si), bl move.w #W_ES, dx bsr.w Left_Reg_Set2 bsr.w Print_Comma bra.w Print_BX_SI ; ***************************************************************************** IO_Op: pop di ;Get the instruction start address. bsr.w P_2BX_Str ;Go print it. btst #8, cx ;Check byte or word... bcs.s IO_Word ; bsr.w Print_DotB move.w #D_AL, dx ; bra.s IO_Size_Set ; IO_Word: bsr.w Print_DotW move.w #W_AX, dx ;Sizes set from here. IO_Size_Set: pop di ;The operands start address. pop si ;The dissassembly address. dc.b $0F,$BA,$F1,$00 ;BCLR #8 _IO_Start: btst #9, cx ; bcs.s _NOT_Ax ; bsr.w Print_Reg ;Print AX/AL. dc.b $0F,$BA,$E9,$00 ;BSET #8 bcs.s _Op1_Set ;Exit if it's the 2nd. bsr.w Print_Comma ;Print a comma. _NOT_Ax: btst #11, cx ;Reg/Imd bcs.s _S_D_ ;Register source. cs:move.b #2, Size ;Set the size to 2. ds:move.b 1(si), bl push cx bsr.w Print_Address pop cx bra.s _S_E_ _S_D_: push dx push cx move.w #W_DX, dx bsr.w Print_Reg pop cx pop dx _S_E_: dc.b $0F,$BA,$E9,$00 ;TAS #8 bcs.s _Op1_Set ;All done. bsr.w Print_Comma not.b ch ; bra.s _IO_Start _Op1_Set: rts ***************************************************************************** Print_I_Byte: bsr.w Print_Hash Print_dcb: move.b #2, cl eor.b bh, bh ;Clear the high byte. bra.s _Print_Imd Print_I_DWord: dc.b $2E,$0F,$BA,$26 ;BTEST for word or double word. dc.w Prefix ;Where to check. dc.b $00 ;Bit 0. bcc.s Print_I_Word ; bsr.w Print_Hash ; move.b #8, cl ; bra.s _Print_Imd ; Print_I_Word: bsr.w Print_Hash ; move.b #4, cl ; _Print_Imd: cs:move.b ImdCol, ah ; move.b #'$', al ; stos.w ; cs:move.b ImdCol, ah ; ******************************************* * A Printing Binary to Hex converter:- * * AH = Colour / Character attributes * * BX = Binary to convert to Ascii Hex * * CL = Count of bytes (1 to 4) * ******************************************* Print_Hex: push.w cx ; asl.b #2, cl ; We are printing backwards:- dc.b $66 ror.w cl, bx ; to the front of the queue. pop.w cx ; Print_Hex_lp: dc.b $66 rol.w #4, bx ; Move to the first nibble. move.b bl, al ; and.b #$f, al ; Mask it off. add.b #$30, al ; cmp.b #$39, al ; ble.s Print_Char ; add.b #7, al ; Print_Char: stos.w ; Print the hex character. dec.b cl ; Decrement the count. bne.s Print_Hex_lp ; Loop again if not zero. rts ******************************************* P_BX_List: move.b cl, al ;The word data... ror.b #2, al ;Move to our data and.w #%1110,ax ;Mask off our bits cs:move.w 2(bx), bx ; add.w ax, bx ; cs:move.w (bx), dx ;The instruction name. cs:move.b InstCol, ah ;The colour. bra.s Print_String ;Print it. ******************************************* * Seperate these at your own peril * ******************************************* P_2BX_Str: cs:move.w 2(bx), dx * cs:move.b InstCol, ah * ******************************************* * print a null terminated string * * ES = The screen segment * * DI = The cursor offset * * CS = The data segment * * DX = The text to print... * ******************************************* Print_String: push.w si move.w dx, si echo_char: cs:move.b (si), al or.b al, al beq.s exit_echo stos.w inc.w si bra.s echo_char exit_echo: pop.w si rts ***************************************************************************** Fable_Op: dec.w si ;Get memory from here. push.w #Fable_Ret ;Return to here. push.w di ;Print here. cs:push.w _HexRoutine-2 ;Get routine from this address. rts ;Can't do JMP [3425] Fable_Ret: push sp ; pop bx ;Access the stack. ss:move.w di, 8(bx) ;Increment the screen position. ss:inc.w 4(bx) ;Increment the dissassembly position. move.w #FData, bx bra.w FData_Start ***************************************************************************** Dummy: pop di move.w #D_Q, dx cs:move.b InstCol, ah bsr.w Print_String pop di pop si ds:move.b (si), bl bra.w Print_dcb ***************************************************************************** INCLUDE N_LIST.S INCLUDE CPUID.S INCLUDE UTILS.S INCLUDE FUNCTION.S INCLUDE HEX.S INCLUDE COLOUR.S INCLUDE DEBUG.S INCLUDE FPU.S InstData INCLUDE J_TABLE.S FData INCLUDE F_TABLE.S ***************************************************************************** DATA ***++++++++++++++++++++++++++++++++++++++++++++++++++*** * Routines strictly for the dissassembler * ***++++++++++++++++++++++++++++++++++++++++++++++++++*** DissRoutine dc.w $51E0,PageDown,0 dc.w $50E0,MoveDown,2 dc.w $4DE0,MoveDown,1 dc.w $48E0,MoveUp,2 dc.w $4BE0,MoveUp,1 dc.w $4300,StepLine,0 dc.w $4400,StepOver,0 dc.w $8500,RunToCurs,0 dc.w $8600,RunProg,0 dc.w $13FF,ToggleReg,0 dc.w $310E,Set_IP,0 dc.w 0 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** * Routines strictly for the Hex display * ***++++++++++++++++++++++++++++++++++++++++++++++++++*** HexRoutine dc.w $48E0,Move_Cursor,-!NUM_CHARS dc.w $49E0,Move_Cursor,-!TOTALCHARS dc.w $4BE0,Move_Cursor,-1 dc.w $4DE0,Move_Cursor,1 dc.w $50E0,Move_Cursor,!NUM_CHARS dc.w $51E0,Move_Cursor,!TOTALCHARS dc.w 0 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** * Routines shared by both main screens * ***++++++++++++++++++++++++++++++++++++++++++++++++++*** SharedKeys dc.w $73E0,DecSegment,0 dc.w $74E0,IncSegment,0 dc.w $8DE0,DecSegment,0 dc.w $91E0,IncSegment,0 dc.w $3E00,ShowScreen,0 dc.w $3F00,ToggleHex,0 dc.w $4000,ShowMCB,0 dc.w $3B00,HelpScreen,0 dc.w $3C00,ColScreen,0 dc.w $2267,Goto,0 LastKey dc.w 0 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** VectorTable dc.w $0000,$0000,OldDivZero,DivZero dc.w $0004,$0000,OldSingle,SingleStep dc.w $000C,$0000,OldBreakPnt,BreakPnt dc.w $0018,$0000,OldIllegal,BrkIllegal dc.w $0090,$0000,OldBreakAdd,BreakAdd dc.w $0084,$0000,OldDOSCall,DOSCall dc.w -1 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** P_List dc.w STATUS,NOPROG,FINISHED,PAUSED,ILLEGAL ***++++++++++++++++++++++++++++++++++++++++++++++++++*** CursorLine dc.b !NUM_LINES TargetData dc.w !SCREENPOS,$B800 Program dc.b 0 Debug dc.b 0 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** MEM_ERROR dc.b "Out of Memory...$" EXE_ERROR dc.b "Failed to load: $" CPU_ERROR dc.b "Choose LIFE... Dump this machine!",13,10,"MonPC needs a 386 or better.$" STATUS dc.b "Status: ",0 NOPROG dc.b "No Program",0 FINISHED dc.b "Terminated",0 PAUSED dc.b "Paused",0 ILLEGAL dc.b "Illegal Instruction",0 CANNOTEXEC dc.b "No Program - No Stack!",0 MYINFO dc.b "MonPC ",0 ST0 dc.b "ST(0)",0 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** CPUTemp dc.b "-?-",0 DOSFREE dc.b "**FREE**",0 DOSPROG dc.b "Executable - ",0 DOSDATA dc.b "Allocated by DOS",0 OWNEDBY dc.b "Environment space owned by ",0 INFOLINE dc.b " MCB | PID | Size | MCB Owner",0 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** DCOLOURS dc.b !ADDR_COL,!HEX_COLA,!HEX_COLB,!INS_COL,!BYTE_COL dc.b !DWORD_COL,!WORD_COL,!REG_COL,!IMD_COL,!ADD_COL PALETTE dc.b $00,$00,$00 ;COLOUR0 <- Background colour. dc.b $0E,$12,$12 ;COLOUR1 <- Border background colour. dc.b $12,$30,$25 ;COLOUR2 <- Border text colour. dc.b $15,$25,$30 ;COLOUR3 <- Address colour dc.b $10,$37,$10 ;COLOUR4 <- Hex colour A. dc.b $05,$20,$05 ;COLOUR5 <- Hex colour B. dc.b $2D,$2D,$00 ;COLOUR6 <- Instruction colour. dc.b $29,$20,$02 ;COLOUR7 <- Byte colour. dc.b $27,$15,$00 ;COLOUR8 <- Word colour. dc.b $32,$14,$04 ;COLOUR9 <- Double word colour. dc.b $2B,$22,$37 ;COLOUR10 <- Register colour. dc.b $2B,$08,$15 ;COLOUR11 <- Immediate data. dc.b $00,$25,$35 ;COLOUR12 <- Address offset. dc.b $34,$34,$34 ;COLOUR13 <- Command highlight colour. dc.b $37,$12,$0E ;COLOUR14 <- Hex cursor highlight. ***************************************************************************** SPALETTE ds.b 15*3 ;Saved colour data. Filename ds.b 150 Arguements ds.b 150 Size ds.b 1 ;The size of the instruction. Prefix ds.b 1 ;Maybe the instruction has a prefix? W_Size ds.b 1 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** AddrCol ds.b 1 HexColA ds.b 1 HexColB ds.b 1 InstCol ds.b 1 ByteCol ds.b 1 DWordCol ds.b 1 WordCol ds.b 1 RegCol ds.b 1 ImdCol ds.b 1 AddCol ds.b 1 ***************************************************************************** ProgScreen ds.w 2 CodSource ds.w 2 HexSource ds.w 2 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** OldSingle ds.w 2 OldBreakPnt ds.w 2 OldBreakAdd ds.w 2 OldDivZero ds.w 2 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** FirstMCB ds.w 1 StartMCB ds.w 1 CodeSegment ds.w 1 PSPSegment ds.w 1 TmpData ds.w 2 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** CursorX ds.b 1 CursorY ds.b 1 HexCursor ds.w 1 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** ParamBlock EnvSegment ds.w 1 ; CmdLine ds.w 2 ; D_FCB_5C ds.w 2 ; D_FCB_6C ds.w 2 ; SS_SP ds.w 2 ; CS_IP ds.w 2 ; **+++** ; S_PSP ds.w 1 ; ***++++++++++++++++++++++++++++++++++++++++++++++++++*** P_CS ds.w 1 P_DS ds.w 1 P_ES ds.w 1 P_FS ds.w 1 P_GS ds.w 1 P_SS ds.w 1 P_SP ds.w 2 DReg ds.w 1 ***++++++++++++++++++++++++++++++++++++++++++++++++++*** NextPage ds.w 1 ;The offset of the next page. CursorPos ds.w 3 ;The cursor position & value. BreakPoints ds.w 3*!MAX_BREAK ;The list of breakpoints. ***************************************************************************** StackBot ds.b 150 StackCentre ds.b 150 STACK ProgEnd