comment ~ 様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様

				  DOS32 Protected Mode Debugger

						Version (see above)

      Copyright (c) Adam Seychell, James B, 1995.  All rights reserved




                           COPYRIGHT

     This software is under copyright and may only be
distributed under the terms and conditions stated in the
General Public Licence. A copy of the licence is distibuted
with this software under the file name GPL.DOC



 I have released the source in the hope it will be useful and that
 if someone has made some improvments and would like to share thier
 work then please send me the new copy so I can release it for next
 versions of DOS32. This source code is written in MASM 6.1 and by
 no means is it written neatly. If someone wants to write thier
 own debugger then best thing would be to use the instruction decode
 routine ( DEBUG.INC ) since this is a general routine for displaying
 486 instructions as a string. The rest of the debugger could be written
 in 32bit C/C++ and while still using ASM for the exception handlers.

 If you have written some code for the debugger or you would like to then
 please contact me by email or snail mail (see address in DOS32.DOC)
 and I will send you the latest copy of the source code so you can
 make your changes. The other option is to send me just the changes
 you have made and I'll implement them to the 'home copy' of the debugger
 source. This is to make sure that all improvments made by everyone who
 has or would like to contirbute, will released in the next version
 of DOS32.

~
;============================================================================
;
;
;         A routine that decodes an instrucion and outputs it in a string
;
;
;
;   FUNCTION:    Decode_instruction
;
;   EXPECTS:      ESI pointing to the instruction
;                 EDI pointing to the output string buffer
;
;
;
;   RETURNS:  *  EDI  pointing the the last character in the string
;                 (string also terminates with zero character).
;             *  ESI  pointing to next instruction.
;             *  If the inscruction was invalid then Carry is set and
;                ESI is unchanged, otherwise carry is clear.
;
;              [MOD_RM_flag]      = non zero if insrcuction contains a
;                                   address operand.
;
;  [MOD_RM_EffectiveAddress]      = address arithmetic of memory operand.
;									undefined if [MOD_RM_flag] == 0.
;
;	[MOD_RM_size]				  = size of memory operand.
;					Far_mem48 	 : 48 bit far pointer
;					Real_mem32	 : 32 bit float
;					Real_mem64	 : 64 bit float
;					Real_mem80	 : 80 bit float
;					Int_mem8 	 : 8 bit integer
;					Int_mem16	 : 16 bit integer
;					Int_mem32	 : 32 bit integer
;					Int_mem64	 : 64 bit integer
;
;
;                [op_seg_overide] = points segment override symbol string.
;                                   or NULL if not exsits
;      [MOD_RM_DefaultSegmentReg] = points default segment override string.
;
;		[JMP_displacement]		  = if insruction has displacment operand
;									then put absolute address in hear.
;								    else = -1
;=============================================================================

.386p
.model flat

Include    debug.inc


	.DATA


Include    opcodes.inc

	.DATA?

JMP_displacement			long		?
Table_end_location          dword		?
MOD_RM_EffectiveAddress  	dword		?
MOD_RM_DefaultSegmentReg 	PBYTE		?
MOD_RM_size              	byte  		?
op_seg_overide  			PBYTE    	?
reg_size        			byte 		?
op_direc        			byte 		?
op_sine         			byte 		?
op_was_done     			byte 		?
force_16bitReg    			byte 		?
MOD_RM_string_pos_save		byte		?
addr_size_prefix  			byte 		?
op_size_prefix  			byte 		?
StringBufferPTR     		PBYTE		?
char_position   			byte 		?
is_float					byte 		?
two_ST_reg_flag				byte		?


	.DATA

ST_symb			db 'st($'

mod_rm_16bit        LABEL   BYTE
db 'bx+si$  '
db 'bx+di$  '
db 'bp+si$  '
db 'bp+di$  '
db 'si$     '
db 'di$     '
db 'bp$     '
db 'bx$     '

EAX_symb        db 'eax$'
ECX_symb        db 'ecx$'
EDX_symb        db 'edx$'
EBX_symb        db 'ebx$'
ESP_symb        db 'esp$'
EBP_symb        db 'ebp$'
ESI_symb        db 'esi$'
EDI_symb        db 'edi$'
EIP_symb        db 'eip$'

ST0_symb		db 'st(0)$'
ST1_symb		db 'st(1)$'
ST2_symb		db 'st(2)$'
ST3_symb		db 'st(3)$'
ST4_symb		db 'st(4)$'
ST5_symb		db 'st(5)$'
ST6_symb		db 'st(6)$'
ST7_symb		db 'st(7)$'

al_symb        db 'al$ '
cl_symb        db 'cl$ '
dl_symb        db 'dl$ '
bl_symb        db 'bl$ '
ah_symb        db 'ah$ '
ch_symb        db 'ch$ '
dh_symb        db 'dh$ '
bh_symb        db 'bh$ '

ES_symb        db 'es$ '
CS_symb        db 'cs$ '
SS_symb        db 'ss$ '
DS_symb        db 'ds$ '
FS_symb        db 'fs$ '
GS_symb        db 'gs$ '
               db '??$ '
               db '??$ '


REPNZ_symb     db 'repnz $'
REPZ_symb      db 'rep   $'
far_symb       db 'ar $'
byte_ptr_symb  db 'Byte ptr $'
word_ptr_symb  db 'Word ptr $'
dword_ptr_symb  db 'Dword ptr $'
qword_ptr_symb  db 'Qword ptr $'
tbyte_ptr_symb  db 'Tbyte ptr $'
real32_ptr_symb  db 'Real32 ptr $'
real64_ptr_symb  db 'Real64 ptr $'
bcd_ptr_symb  db 'BCD ptr $'
CR0_symb       db 'CR0$'
CR1_symb       db 'CR1$'
CR2_symb       db 'CR2$'
CR3_symb       db 'CR3$'
CR4_symb       db 'CR4$'
CR5_symb       db 'CR5$'
CR6_symb       db 'CR6$'
CR7_symb       db 'CR7$'

DR0_symb       db 'DR0$'
DR1_symb       db 'DR1$'
DR2_symb       db 'DR2$'
DR3_symb       db 'DR3$'
DR4_symb       db 'DR4$'
DR5_symb       db 'DR5$'
DR6_symb       db 'DR6$'
DR7_symb       db 'DR7$'

TR0_symb       db 'TR0$'
TR1_symb       db 'TR1$'
TR2_symb       db 'TR2$'
TR3_symb       db 'TR3$'
TR4_symb       db 'TR4$'
TR5_symb       db 'TR5$'
TR6_symb       db 'TR6$'
TR7_symb       db 'TR7$'
instruc_CBW    db 'cbw   $'
instruc_CWD    db 'cwd   $'




	.CODE

Decode_instruction PROC PRIVATE USES EAX EBX ECX EDX
LOCAL   THE_symbol,old_ESI      :dword
local   format_ends             :Dword



        cld
        mov		JMP_displacement,-1
        mov     StringBufferPTR,edi
        mov     char_position,0
        mov     op_seg_overide,NULL
        mov 	addr_size_prefix,0
        mov     op_size_prefix,0
        mov     op_was_done,0
        mov     reg_size,1
        mov     op_direc,0
        mov     force_16bitReg,0
        mov     op_sine,0
        mov     old_ESI,esi
        mov      MOD_RM_flag,FALSE
        mov     MOD_RM_EffectiveAddress,0
        mov  	MOD_RM_size,Int_mem32
        mov     MOD_RM_DefaultSegmentReg,offset DS_symb
        mov		is_float,FALSE
        mov		two_ST_reg_flag,FALSE

        mov  ecx,5

prefix_find_loop:
        ;------------- Get segment overide prefixes ---------
        mov     al,[esi]
        .if     al == 00101110b
                mov     op_seg_overide,offset CS_symb
        .elseif al == 00111110b
                mov     op_seg_overide,offset DS_symb
        .elseif al == 00100110b
                mov     op_seg_overide,offset ES_symb
        .elseif al == 01100100b
                mov     op_seg_overide,offset FS_symb
        .elseif al == 01100101b
                mov     op_seg_overide,offset GS_symb
        .elseif al == 00110110b
                mov     op_seg_overide,offset SS_symb
        .else
          dec esi
        .endif
          inc  esi
        ;------------ plot REPNZ/REPZ pefixes ------------
        .if     al == 11110010b
                mov     edx,offset REPNZ_symb
                call    string
                inc     esi
        .elseif al == 11110011b
                mov     edx,offset REPZ_symb
                call    string
                inc     esi
        .endif

        ;------------ get size prefixes -------------------
        mov     al,[esi]
        .if     al == 01100111b
            mov    addr_size_prefix,1
            inc    esi
        .elseif al == 01100110b
            mov    op_size_prefix,1
            inc    esi
        .endif
        dec     ecx
        jnz prefix_find_loop


        ;---------- get the instruction ------------
        ; is a ESC opcode ?
        ; if so then decode from FPU instruction table
        ; otherwise use CPU instruction table. this narrows down the search
        ;

    	mov		al,[esi]
        and		al,11111000b
        .if 	al == 11011000b
            mov  is_float,TRUE
	        mov  edi,offset The_FPU_Instruction_Table
            mov	 [Table_end_location], FPU_Instruction_Definitions_End
        .else
	        mov  edi,offset The_CPU_Instruction_Table
            mov	 [Table_end_location], CPU_Instruction_Definitions_End
        .endif


        xor    ebx,ebx
Find_What_Loop:
        .if      edi == [Table_end_location]
                mov    al,'?'
                call   print_char
                mov     esi,old_ESI
                inc     esi
                movzx   edi,char_position
                add     edi,StringBufferPTR
                mov     byte ptr [edi],0
                stc
                ret
        .endif

        .if     byte ptr [edi] == Symbol
            inc     edi
	        mov     THE_symbol,edi
            add     edi, 7
        .endif
         push    edi
         push    esi
		 mov	 cl,4
CheckInstr_Loop:
         mov    al,[esi]
         mov    BL,[edi]
         cmp	bl,NULLER
		 je  finished_it
         sub    bl,TTTTTTTT
         cmp    bl  ,( the_last_T - TTTTTTTT)
         jae not_opcode
          and     al,opcode_mask_vlaues[ebx] ; mask the instruction opcode
          cmp     al,[edi+4]                 ; compare with the opcode
          jne contSrch_
          .IF ( is_float == TRUE) && ( BL == (mod_TTT_rm-TTTTTTTT) )
            cmp  byte ptr [esi], 11000000b
            jae contSrch_
          .ENDIF
          inc     esi                     ; instruction pointer
not_opcode:
        inc     edi                     ; instruction table pointer
        dec		cl
        jnz   CheckInstr_Loop
        jmp   finished_it

contSrch_: pop     esi
           pop     edi
contSrch:  add    edi,7
           jmp     Find_What_Loop



finished_it:                   ; finishe searching instruction
        pop     esi
        pop     edi
        cmp  byte ptr [esi],0fh
        jne @f
        cmp  byte ptr [edi+1],NULLER
        je contSrch
@@:

;===============================================


        ;--------- plot the instuction symbol on the screen ---------
        push    esi
        mov     esi,THE_symbol

    .IF op_size_prefix == 1
      .IF   dword ptr [esi] == ' qdc'
          mov  edx,offset instruc_CWD
          call   string
          jmp InstPrnted
       .ELSEIF  dword ptr [esi] == 'edwc'
          mov  edx,offset instruc_CBW
          call   string
          jmp InstPrnted
      .ENDIF
    .ENDIF

        mov     ecx,7
        .Repeat
             lodsb
             call    print_char
        .UntilCXZ
        .if  byte ptr [edi-1] == 'f'
            mov  edx,offset far_symb
            call   string
            mov MOD_RM_size, Far_mem48
        .endif
InstPrnted:
        pop     esi

                ; EDI = OFFSET OF THE INSTRUC NULLER

        mov     format_ends,edi
        add     format_ends,4



Operand_decode_loop:
        ;---------- decode the operands ---------------------
        mov     al,[esi]				; ESI -> instruction opcode
        mov     bl,[edi]				; EDI -> opcode table defs


        .IF		BL   ==      TTTTTTTw
                and     al,1
                mov     reg_size,al

        .ELSEIF BL   ==      TTTTTreg
                call Plot_reg_field

        .ELSEIF BL   ==      TTTTT_st

        		.if (two_ST_reg_flag)
				   .if (op_direc)
    				  call 	Plot_reg_field
                      mov   al,','
                      call  print_char
                      mov   al,0
                   .else
                      mov  	al,0
    				  call 	Plot_reg_field
                      mov   al,','
                      call  print_char
                      mov   al,[esi]
                   .endif
                .endif
                call Plot_reg_field

        .ELSEIF BL   ==      TTTTTTdw
                test	al,00000001b
                setnz   reg_size
                test	al,00000010b
                setnz   op_direc
        .ELSEIF BL   ==      TTTTTTdT
                test	al,00000010b
                setnz   op_direc
        .ELSEIF BL   ==      set_direc
                mov     op_direc,1
                dec     esi
        .ELSEIF BL   ==      TTTTwreg
                test	al,00001000b
                setnz   reg_size
                call Plot_reg_field

        .ELSEIF BL   ==      TTTTTTsT
                test	al,00000010b
                setnz   op_sine

        .ELSEIF BL   ==      TTTTTTsw
                test	al,00000001b
                setnz   reg_size
                test	al,00000010b
                setnz   op_sine

        .ELSEIF BL   ==      REG_CL
                                call    Print_comma
                                mov     edx,offset cl_symb
                                call string
                                DEC  ESI
        .ELSEIF BL   ==      REG_EAX
                        	call    Print_comma
                        	xor al,al
                        	call Plot_reg_field
                                DEC  ESI
        .ELSEIF BL   ==      SetEndCharTo_W
                               DEC  ESI

                               sub     char_position,2
                               mov al,'b'
                              .if reg_size == 1
                                     .if op_size_prefix == 1
                                       mov al,'w'
                                         .if  byte ptr [esi] == 11001111b
                                          mov al,' '
                                         .endif
                                      .else
                                        mov al,'d'
                                      .endif
                              .endif
                                call    print_char
                                inc     char_position
                              .if op_seg_overide != NULL
                                 mov edx,op_seg_overide
                                 call string
                                 mov  al,':'
                                 call print_char
                              .endif

        .ELSEIF BL   ==      TT_sreg3_TTT
                           	shr  al,3
                           	call Plot_Sreg_field

        .ELSEIF BL   ==      TTT_sreg2_TTT
                           	shr  al,3
                           	and  al,3
                           	call Plot_Sreg_field
        .ELSEIF BL   ==      port_number_IN
                                xor     eax,eax
                                call Plot_reg_field
                                call    Print_comma
                                mov     eax,[esi]
                                call    hex_byte
        .ELSEIF BL   ==      port_number_OUT
                                mov     eax,[esi]
                                call    hex_byte
                                mov     al,','
                                call    print_char
                                xor     eax,eax
                                call Plot_reg_field
        .ELSEIF BL   ==      port_DX_OUT
                                mov     edx,offset EDX_symb+1
                                call    string
                                mov     al,','
                                call    print_char
                                xor     eax,eax
                                call Plot_reg_field
                                dec     esi
        .ELSEIF BL   ==      port_DX_IN
                                xor     eax,eax
                                call Plot_reg_field
                                mov     al,','
                                call    print_char
                                mov     edx,offset EDX_symb+1
                                call    string
                                dec     esi
        .ELSEIF BL   ==      mod_zxreg_rm
                        shr     al,3
	                mov     bl,reg_size
	                mov     reg_size,1
        	        call    Plot_reg_field
                        call    Print_comma
                       .if bl == 1
                        mov   force_16bitReg,1
                         mov  edx,offset word_ptr_symb
                       .else
                         mov  edx,offset byte_ptr_symb
                       .endif
                        shr     al,3
                        .if al != 11b
                          call  string
                        .endif
                        mov     reg_size,0
                        call    extract_mod_rm


        .ELSEIF BL   ==      mod_TTT_rm
                mov		bl,char_position    		; save char position
        		mov     MOD_RM_string_pos_save,bl
                call    extract_mod_rm

        .ELSEIF BL   ==      mod_reg_rm
                         .if op_direc == 1
                                shr    al,3
                                call Plot_reg_field
                                mov     al,','
                                call    print_char
                                call    extract_mod_rm
                         .else
                                push    esi
                                call    extract_mod_rm
                                mov     edx,esi
                                pop     esi
                                mov     al,','
                                call    print_char
                                mov     al,[esi]
                                shr    al,3
                                call Plot_reg_field
                                mov     esi,edx
                         .endif
        .ELSEIF  BL == mod_sreg3_rm
                         mov    force_16bitReg,1
                         .if op_direc == 1
                                shr    al,3
                                call Plot_Sreg_field
                                mov     al,','
                                call    print_char
                                call    extract_mod_rm
                         .else
                                push    esi
                                call    extract_mod_rm
                                mov     edx,esi
                                pop     esi
                                mov     al,','
                                call    print_char
                                mov     al,[esi]
                                shr    al,3
                                call Plot_Sreg_field
                                mov     esi,edx
                         .endif
        .ELSEIF  BL == TT_CR0_reg
                         mov     edx,offset CR0_symb
                         call    plot_special_register
        .ELSEIF  BL == TT_DR0_reg
                         mov     edx,offset DR0_symb
                         call    plot_special_register
        .ELSEIF  BL == TT_TR0_reg
                         mov     edx,offset TR0_symb
                         call    plot_special_register


        .ELSEIF  BL == full_displacement
                         mov    eax,[esi]
                         add    eax,esi
                         add    eax,4
                         mov    JMP_displacement,eax
                         call    hex_dword
                      	  add    esi,3

        .ELSEIF  BL == Short_displacement
                         movsx  eax,byte ptr [esi]
                         add    eax,esi
                         inc    eax
                         mov	JMP_displacement,eax
                         call   hex_dword

        .ELSEIF  BL == full_offset_selector
                         mov    ax,[esi+4]
                         call   hex_word
                         mov    al,':'
                         call   print_char
                         mov    eax,[esi]
                         call    hex_dword
                         add    esi,5

        .ELSEIF  BL == unsigned_full_offset
	                call    Print_comma
                        mov     op_was_done,1
                        call    plot_seg_reg
	                mov     al,'['
                        call    print_char
                        mov     eax,[esi]
                      .if addr_size_prefix == 1
                         movsx  eax,ax
                         add    MOD_RM_EffectiveAddress,eax
                         call  hex_dword
                         inc   esi
                      .else
                         add    MOD_RM_EffectiveAddress,eax
                         call  hex_dword
                         add    esi,3
                      .endif
                        mov     al,']'
                        call    print_char
                        mov     MOD_RM_flag,TRUE

        .ELSEIF  BL == immediate_8bit
                call    Print_comma
                mov     op_was_done,1
                mov     al,[esi]
                call	hex_byte

        .ELSEIF BL == immediate_16bit
                call    Print_comma
                mov     op_was_done,1
                mov     eax,[esi]
                call    hex_word
                inc     ESI

        .ELSEIF BL == immediate_data
                call    Print_comma
                mov      eax,[esi]
               .if op_sine == 1
                    movsx      eax,byte ptr [esi]
                   .if op_size_prefix == 1
                      call  hex_word
                   .else
                      call  hex_dword
                   .endif
               .elseif  reg_size == 1
                  .if op_size_prefix == 1
                     call  hex_word
                     add   esi,1
                   .else
                     call hex_dword
                     add   esi,3
                   .endif
               .else
                 call hex_byte
               .endif
                call    Set_OP_size_flag

		.ELSEIF BL == TTTTTdTT
                test	al,00000100b
                setnz   op_direc
                mov		two_ST_reg_flag,TRUE

        .ELSEIF BL == Real_mem32
        		mov		MOD_RM_size,BL
                mov     edx,offset real32_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi

        .ELSEIF BL == Real_mem64
        		mov		MOD_RM_size,BL
                mov     edx,offset real64_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi

        .ELSEIF BL == Real_mem80
        		mov		MOD_RM_size,BL
                mov     edx,offset tbyte_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi

        .ELSEIF BL == Int_mem32
        		mov		MOD_RM_size,BL
                mov     edx,offset dword_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi

        .ELSEIF BL == Int_mem16
        		mov		MOD_RM_size,BL
                mov     edx,offset word_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi

        .ELSEIF BL == Int_mem64
        		mov		MOD_RM_size,BL
                mov     edx,offset qword_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi

        .ELSEIF BL == BCD_mem80
        		mov		MOD_RM_size,BL
                mov     edx,offset bcd_ptr_symb
                mov		al,MOD_RM_string_pos_save
                call	insert_string
        		dec		esi


        .ENDIF

        inc     edi
        inc     esi
        cmp     byte ptr [edi],NULLER
        je exit
        cmp     edi,format_ends
        jb   Operand_decode_loop
exit:   movzx   edi,char_position
        add     edi,StringBufferPTR
        mov     byte ptr [edi],0
        clc
        ret



Decode_instruction ENDP



;======================================================================
;
; PLOTS A COMMA ON IF NEEDS TO
;
;======================================================================
Print_comma PROC PRIVATE USES EAX
                .if op_was_done == 1
                  mov     al,','
                  call    print_char
               .endif
                ret
Print_comma ENDP

;======================================================================
;
; PLOTS A SPECIAL CPU REGISTER    ( EXPECTS edx -> REGISTER TABLE )
;
;======================================================================
plot_special_register PROC PRIVATE
      .if op_direc == 1
        and     al,00111000B
        shr     al,1
        movzx   eax,al
        add     edx,eax
        call    string
        mov     al,','
        call    print_char
        mov     al,[esi]
        call    Plot_reg_field
     .else
        call Plot_reg_field
        call    Print_comma
        and     al,00111000B
        shr     al,1
        movzx   eax,al
        add     edx,eax
        call    string
      .endif
        ret
plot_special_register ENDP

;======================================================================
;
; PLOTS A REGISTER of AL given it's "reg_size"
;
;======================================================================
Plot_reg_field PROC PRIVATE USES EDX EAX
        mov 	op_was_done,1
    	and    al,7
        movzx  edx,al
        .if ( is_float != 0)
        	push	edx
        	mov    edx,Offset ST_symb
	        call   string
            pop		eax
            add		al,'0'
            call	print_char
            mov		al,')'
            call	print_char
        .elseif force_16bitReg != 1
            shl    edx,2
 	       .if  reg_size == 1
                   add     edx,offset EAX_symb
	          .if op_size_prefix == 1
                     inc  edx
	          .endif
                .else
                   add     edx,offset al_symb
	        .endif
        .else
            shl    edx,2
           add     edx,offset EAX_symb+1
        .endif
        call   string
        call    Set_OP_size_flag
        ret
Plot_reg_field  ENDP


;=======================================================================
Set_OP_size_flag        PROC PRIVATE
        .if force_16bitReg != 1
               .if  reg_size == 1
                  .if op_size_prefix == 1
                    mov  MOD_RM_size, Int_mem16
                  .endif
              .else
                    mov  MOD_RM_size, Int_mem8
              .endif
        .else
           mov  MOD_RM_size, Int_mem16
        .endif
        ret
Set_OP_size_flag ENDP

;======================================================================
;
; PLOTS A SEGMENT REGISTER of AL
;
;======================================================================
Plot_Sreg_field PROC PRIVATE USES EDX EAX
        mov    op_was_done,1
		and    al,7
        movzx  edx,al
        shl    edx,2
        add    edx,offset ES_symb
        call   string
        mov    MOD_RM_size, Int_mem16
        ret
Plot_Sreg_field  ENDP

;=======================================================================
extract_mod_rm PROC PRIVATE
        .if addr_size_prefix == 1
          call Extract16bit_mod_rm
        .else
          call Extract32bit_mod_rm
        .endif
        call    Set_OP_size_flag
         ret
extract_mod_rm ENDP




;=======================================================================
;
;   plots the data for the 32bit mod r/m
;
; Expects:  esi -> instruction.
; Returns:  esi -> end byte of address field.
;=======================================================================
Extract32bit_mod_rm PROC PRIVATE USES EDX EAX
LOCAL   op_rm     :byte
LOCAL   op_mod    :byte
LOCAL   sib_base  :byte
LOCAL   sib_index :byte
LOCAL   sib_scale :byte

                mov     op_was_done,1
                mov     al,[esi]
                mov     op_rm,al
                and     op_rm,7
                shr     al,6
                mov     op_mod,al


                .if     op_mod  == 11b
                        mov     al,op_rm
                        call    Plot_reg_field

                .elseif op_rm  != 100b

                        mov     MOD_RM_flag,TRUE
                        call    plot_seg_reg
                        mov     al,'['
                        call    print_char

                        .if  op_rm == 101b
                         .if     op_mod == 00b
                             jmp @f
                         .endif
                          mov     MOD_RM_DefaultSegmentReg,offset SS_symb
                        .endif

                        mov    al,op_rm
        	        and    al,7
        	        movzx  edx,al
                        shl    edx,2
                        mov     eax,registers_save.prg_eax[edx]
                        add     MOD_RM_EffectiveAddress,eax
                        add     edx,offset EAX_symb
                        call   string
                          mov     al,'+'
                        .if   op_mod == 01b
                          call    print_char
                          inc   esi
                          movsx   eax,byte ptr [esi]
                          add     MOD_RM_EffectiveAddress,eax
                          call   hex_dword
                        .elseif op_mod == 10b
                          call    print_char
@@:                       mov   eax,[esi+1]
                          add     MOD_RM_EffectiveAddress,eax
                          call  hex_dword
                          add   esi,4
                        .endif

                        mov     al,']'
                        call    print_char

                .ELSE   ;=================  S-I-B  ===========

                        mov      MOD_RM_flag,TRUE
                        inc     esi
                        mov     al,[esi]
                        mov     sib_base,al
                        and     sib_base,7
                        shr     al,3
                        mov     sib_index,al
                        and     sib_index,7
                        shr     al,3
                        mov     sib_scale,al

                        call    plot_seg_reg
                        mov     al,'['
                        call    print_char



                        .if  sib_base == 101b
                          .if     op_mod == 00b
                             mov eax,[esi+1]
                             add     MOD_RM_EffectiveAddress,eax
                             call  hex_dword
                             add   esi,4
                             jmp @F
                          .endif
                          mov     MOD_RM_DefaultSegmentReg,offset SS_symb
                         .endif

                        .if  sib_base == 100b
                         mov     MOD_RM_DefaultSegmentReg,offset SS_symb
                        .endif

                         ;--------- plot base -------
                         movzx  edx,sib_base
                         shl    edx,2
                         mov     eax,registers_save.prg_eax[edx]
                         add     MOD_RM_EffectiveAddress,eax
                         add    edx,offset EAX_symb
                         call   string
@@:
                         ;--------- plot sacled index -------
                        .if sib_index != 100b
                                mov  al,'+'
                                call print_char
                               .if sib_scale !=0
                                        mov  al,1
	                                mov  cl,sib_scale
	                                shl  al,cl
	                                add  al,'0'
	                                call print_char
                                        mov  al,'*'
	                                call print_char
	                         .endif
                                 movzx  edx,sib_index
	                         shl    edx,2
                                 mov     eax,registers_save.prg_eax[edx]
                                 mov   cl,sib_scale
                                 shl   eax,cl
        	                 add     MOD_RM_EffectiveAddress,eax
                                 add    edx,offset EAX_symb
                                 call   string
                        .endif
                         ;--------- plot displacement -------
                         mov  al,'+'
                        .if   op_mod == 01b
                          call print_char
                          inc   esi
                          movsx  eax,byte ptr [esi]
                          add     MOD_RM_EffectiveAddress,eax
                          call  hex_dword
                        .elseif op_mod == 10b
                          call print_char
                          mov  eax,[esi+1]
                          add     MOD_RM_EffectiveAddress,eax
                          call  hex_dword
                          add   esi,4
                        .endif

	                mov     al,']'
	                call    print_char
                .endif

        ret
Extract32bit_mod_rm ENDP

;=======================================================================0
;
;   plots the data for the 16bit mod r/m
;
; Expects:  esi -> instruction.
; Returns:  esi -> end byte of address field.
;=======================================================================0
Extract16bit_mod_rm PROC PRIVATE USES EDX EAX
LOCAL   op_rm     :byte
LOCAL   op_mod    :byte
                mov     op_was_done,1
                mov     al,[esi]
                mov     op_rm,al
                and     op_rm,7
                shr     al,6
                mov     op_mod,al
                .IF     op_mod  == 11b
                       ;========== rm = register ===================
                        mov     al,op_rm
                        call    Plot_reg_field

                .ELSE  ;========== rm = memory ===================
                        mov      MOD_RM_flag,TRUE
                        call    plot_seg_reg
                        mov     al,'['
                        call    print_char

                        .if  op_rm == 110b
                          .if     op_mod == 00b
                             jmp @f
                          .endif
                          mov     MOD_RM_DefaultSegmentReg,offset SS_symb
                        .endif

                        .if  op_rm == 011b
                         mov     MOD_RM_DefaultSegmentReg,offset SS_symb
                        .elseif op_rm == 010b
                         mov     MOD_RM_DefaultSegmentReg,offset SS_symb
                        .endif

                        mov    al,op_rm
        	        and    al,7
                        movzx  edx,al
                        .if al == 0
                           mov     eax,registers_save.prg_ebx
                           add     eax,registers_save.prg_esi
                        .elseif al == 1
                           mov     eax,registers_save.prg_ebx
                           add     eax,registers_save.prg_edi
                        .elseif al == 2
                           mov     eax,registers_save.prg_ebp
                           add     eax,registers_save.prg_esi
                        .elseif al == 3
                           mov     eax,registers_save.prg_ebp
                           add     eax,registers_save.prg_edi
                        .elseif al == 4
                           mov     eax,registers_save.prg_esi
                        .elseif al == 5
                           mov     eax,registers_save.prg_edi
                        .elseif al == 6
                           mov     eax,registers_save.prg_ebp
                        .elseif al == 7
                           mov     eax,registers_save.prg_ebx
                        .endif
                        movsx   eax,ax
                        add     MOD_RM_EffectiveAddress,eax
                        shl     edx,3
                        add     edx,offset mod_rm_16bit
                        call   string
                        mov     al,'+'
                        .if   op_mod == 01b
                          call    print_char
                          inc   esi
                          movsx  eax,byte ptr [esi]
                          add    MOD_RM_EffectiveAddress,eax
                          call  hex_word
                        .elseif op_mod == 10b
                          call    print_char
@@:                       movsx  eax,word ptr [esi+1]
                          add     MOD_RM_EffectiveAddress,eax
                          call hex_word
                          add   esi,2
                        .endif

                        mov     al,']'
                        call    print_char
        .endif
        ret
Extract16bit_mod_rm ENDP




hex_dword        PROC PRIVATE USES ECX EAX
        mov     cl,8
        call    hex_print
        ret
hex_dword       ENDP
hex_byte        PROC PRIVATE USES ECX EAX
        rol     eax,24
        mov     cl,2
        call    hex_print
        ret
hex_byte       ENDP
hex_word        PROC PRIVATE USES ECX EAX
        rol     eax,16
        mov     cl,4
        call    hex_print
        ret
hex_word       ENDP


;--------------------------------------------
; expects 	CL number of nibbles (max 8)
;           EAX = value
;
; does not print more than one leading zero

hex_print        PROC PRIVATE USES EDX
        mov     edx,eax
        .if		eax < 10000000h
   		 mov     al,'0'
         call    print_char
        .endif
        mov		ch,0
he_plotloop:
        rol     edx,4
        movzx   eax,dl
        and     al,0fh
        cmp 	al,ch
        je @f
        mov     al,HexChars[eax]
        mov     ch,-1
        call    print_char
@@:     dec     cl
        jnz he_plotloop
        ret

HexChars       db '0123456789abcdef'
hex_print       ENDP


string  PROC PRIVATE USES EAX
strloop:    mov     al,[edx]
	        cmp     al,'$'
            je exit
            call print_char
        	inc     edx
	        jmp strloop
exit:        ret
string  ENDP


print_char    PROC PRIVATE USES EDX
        movzx   edx,char_position
        add     edx,StringBufferPTR
        mov     [edx],al
        inc     char_position
        ret
print_char      ENDP

;=========================================================================
plot_seg_reg PROC PRIVATE
    .if op_seg_overide != NULL
         mov    edx,op_seg_overide
         call   string
         mov     al,':'
         call    print_char
     .endif
        ret
plot_seg_reg ENDP

;=========================================================================
insert_string PROC PRIVATE USES EDI ESI ECX

		cld
        and     eax,0ffh
        cmp		al,char_position
        jb  Doit
        call  	string
        ret

Doit:
        mov		ecx,0
@@:		cmp  byte ptr [edx+ecx],'$'
        lea  ecx,[ecx+1]
        jne @b
        dec   ecx

        movzx	esi,char_position
        add     esi,StringBufferPTR
        lea     edi,[esi+ecx]

        movzx	ecx,char_position
        sub	    ecx,eax
        push	edi
        dec     esi
        dec     edi
        std
        rep		movsb

        mov		char_position,al
   		call	string

		pop		eax
        sub		eax,StringBufferPTR
        mov		char_position,AL

		cld

        ret
insert_string ENDP

END