├── LDebugB ├── MAKE.BAT ├── LDEBUGB.TXT └── LDEBUGB.ASM ├── Samples ├── MAKEJ.BAT ├── DPMICL16.SCR ├── DPMICL16.ASM ├── DPMICL32.ASM ├── DPMIBK16.ASM └── DPMIBK32.ASM ├── Test ├── TEST1.SCR ├── PRESEG.ASM ├── PRESEGD.ASM ├── PREBAD.ASM ├── PREBADD.ASM ├── PREREP.ASM ├── PREREPD.ASM ├── PRE67.ASM ├── PRE67D.ASM ├── PRE66.ASM ├── PRE66D.ASM ├── TERM.ASM ├── CALLJMPD.ASM ├── CALLJMP.ASM ├── PRESTR.ASM ├── PRESTRD.ASM ├── DATA1MB.ASM ├── TESTI2F.ASM ├── LEAVE.ASM ├── CODETS32.ASM ├── DBGMBR.ASM ├── TESTQQ.ASM ├── UNREAL.ASM ├── HUGESEG.ASM └── INITPM.INC ├── MAKE.BAT ├── MAKECW.BAT ├── MAKECM.BAT ├── src ├── INSTR.ORD ├── TRAPR.INC ├── INSTR.KEY ├── TRAPD.INC ├── DPRINTFR.INC ├── DPRINTF.INC ├── TRAPPL.INC ├── TRAPP.INC ├── FPTOSTR.INC ├── INSTR.SET ├── TRAPPV.INC └── DISTBL.INC ├── MAKEX.BAT ├── Makefile ├── README.TXT └── HISTORY.TXT /LDebugB/MAKE.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | jwasm -mz LDEBUGB.ASM 3 | -------------------------------------------------------------------------------- /Samples/MAKEJ.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem assemble the samples which are written in MASM syntax. 3 | rem JWasm is used. 4 | jwasm -nologo -bin -Fo DPMICL16.COM DPMICL16.ASM 5 | jwasm -nologo -bin -Fo DPMIBK16.COM DPMIBK16.ASM 6 | jwasm -nologo -mz DPMICL32.ASM 7 | jwasm -nologo -mz DPMIBK32.ASM 8 | -------------------------------------------------------------------------------- /LDebugB/LDEBUGB.TXT: -------------------------------------------------------------------------------- 1 | 2 | About LDebugB 3 | 4 | LDebugB works in cooperation with Jemm's FASTBOOT option and 5 | JLM fastboot.dll. It loads file DEBUGB.BIN, the boot variant of 6 | Debug, and supplies it to the JLM. After pressing Ctrl-Alt-Del, 7 | the debugger should become active, just before the boot sector 8 | code will be run. 9 | 10 | -------------------------------------------------------------------------------- /Test/TEST1.SCR: -------------------------------------------------------------------------------- 1 | 2 | ; test a(ssemble) cmd 3 | 4 | a 5 | mov cx,1 6 | movzx cx,cl 7 | movzx ecx,cl 8 | mov cx,[0] 9 | movzx cx,[0] 10 | movzx ecx,[0] ; should be an error 11 | movzx ecx,wo [0] 12 | call far 0:0 13 | call ne 0 ; should be ok 14 | cmp [0],0 ; should be an error 15 | cmp wo [0],0 16 | 17 | u 100 l 30 18 | q 19 | -------------------------------------------------------------------------------- /MAKE.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | if not exist build\NUL mkdir build 3 | echo creating debug.com 4 | jwasm -nologo -bin -Fobuild\DEBUG.COM -Flbuild\DEBUG.LST src\debug.asm 5 | echo creating debugx.com 6 | jwasm -nologo -D?DPMI=1 -DALTVID=1 -bin -Fo build\DEBUGX.COM -Flbuild\DEBUGX.LST src\debug.asm 7 | rem ml -c -nologo -D?DPMI=1 -DALTVID=1 -Fo build\DEBUGX.OBJ -Flbuild\DEBUGX.LST src\debug.asm 8 | -------------------------------------------------------------------------------- /Test/PRESEG.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: handling of unused segment prefixes 3 | ;--- assemble: jwasm -mz preseg.asm 4 | 5 | .286 6 | .model small 7 | .stack 256 8 | .dosseg 9 | .386 10 | 11 | .code 12 | 13 | main proc c 14 | 15 | int 3 16 | ret 17 | db 26h,2eh,36h,3eh,64h,65h 18 | movsw 19 | 20 | main endp 21 | 22 | start proc 23 | call main 24 | mov ax,4c00h 25 | int 21h 26 | start endp 27 | 28 | END start 29 | 30 | -------------------------------------------------------------------------------- /Test/PRESEGD.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: handling of unused segment prefixes 3 | ;--- assemble: jwasm -mz presegd.asm 4 | 5 | .386 6 | .MODEL tiny 7 | .stack 1024 8 | .dosseg 9 | 10 | .code 11 | 12 | main proc c 13 | 14 | int 3 15 | ret 16 | db 26h,2eh,36h,3eh,64h,65h 17 | movsd 18 | 19 | main endp 20 | 21 | start32 proc 22 | call main 23 | mov ax,4c00h 24 | int 21h 25 | start32 endp 26 | 27 | include initpm.inc 28 | 29 | END start 30 | 31 | -------------------------------------------------------------------------------- /Test/PREBAD.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: handling of "bad" prefixes 3 | ;--- assemble: jwasm -mz prebad.asm 4 | 5 | .286 6 | .model small 7 | .stack 256 8 | .dosseg 9 | .386 10 | 11 | .code 12 | 13 | main proc c 14 | 15 | int 3 16 | ret 17 | db 67h 18 | push 2074h 19 | db 66h 20 | mov al,ds:[0] 21 | db 26h 22 | xchg al, ah 23 | 24 | main endp 25 | 26 | start proc 27 | call main 28 | mov ax,4c00h 29 | int 21h 30 | start endp 31 | 32 | END start 33 | 34 | -------------------------------------------------------------------------------- /MAKECW.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem Builds mktables.exe. Open Watcom's C compiler is used. 3 | rem This step is only required if one of the following files were modified: 4 | rem 1) instr.set 5 | rem 2) instr.key 6 | rem 3) instr.ord 7 | rem 4) mktables.c 8 | 9 | set WATCOM=\watcom 10 | %WATCOM%\binnt\wcc -q -ox -ms -i%WATCOM%\h -3 -fo=build\mktables.obj src\mktables.c 11 | %WATCOM%\binnt\wlink format dos f build\mktables.obj n build\mktables.exe libpath %WATCOM%\lib286\dos libpath %WATCOM%\lib286 op q,m=build\mktables.map 12 | -------------------------------------------------------------------------------- /Test/PREBADD.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: handling of "bad" prefixes 3 | ;--- assemble: jwasm -mz prebadd.asm 4 | 5 | .386 6 | .MODEL tiny 7 | .stack 1024 8 | .dosseg 9 | 10 | .code 11 | 12 | main proc c 13 | 14 | int 3 15 | ret 16 | db 67h 17 | push 12345678h 18 | db 66h 19 | mov al,ds:[0] 20 | db 26h 21 | xchg al, ah 22 | 23 | main endp 24 | 25 | start32 proc 26 | call main 27 | mov ax,4c00h 28 | int 21h 29 | start32 endp 30 | 31 | include initpm.inc 32 | 33 | END start 34 | 35 | -------------------------------------------------------------------------------- /MAKECM.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem Builds mktables.exe. using MS Visual C++ 1.52 3 | rem This step is only required if one of the following files were modified: 4 | rem 1) instr.set 5 | rem 2) instr.key 6 | rem 3) instr.ord 7 | rem 4) mktables.c 8 | 9 | set MSVC=\msvc 10 | set LIB=%MSVC%\lib 11 | %MSVC%\bin\cl -c -nologo -G3 -Fobuild\mktables.obj -I%MSVC%\include src\mktables.c 12 | rem %MSVC%\bin\link /NOLOGO build\mktables.obj,build\mktables.exe,build\mktables.map /NON; 13 | %MSVC%\bin\link build\mktables.obj,build\mktables.exe,build\mktables.map; 14 | -------------------------------------------------------------------------------- /Test/PREREP.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: handling of rep prefixes 3 | ;--- assemble: jwasm -mz prerep.asm 4 | 5 | .286 6 | .model small 7 | .stack 256 8 | .dosseg 9 | .386 10 | 11 | .code 12 | 13 | main proc c 14 | 15 | int 3 16 | ret 17 | rep movsb 18 | repnz cmpsb 19 | repz scasb 20 | repne cmpsb 21 | repe scasb 22 | rep movsb [edi],[esi] 23 | repnz cmpsb [esi],[edi] 24 | repz scasb [edi] 25 | repne cmpsb [esi],[edi] 26 | repe scasb [edi] 27 | 28 | main endp 29 | 30 | start proc 31 | call main 32 | mov ax,4c00h 33 | int 21h 34 | start endp 35 | 36 | END start 37 | 38 | -------------------------------------------------------------------------------- /src/INSTR.ORD: -------------------------------------------------------------------------------- 1 | # This is the file "instr.ord". It gives the order preferences that 2 | # must be respected by the assembler. 3 | 4 | # Comments are as in the main instruction set file "instr.set." 5 | 6 | # Each (non-comment) line should be a pair of keys. The table-generating 7 | # program will check that the order of instruction variants for each 8 | # instruction in the file "instr.set" is compatible with each pair. 9 | # If not, it will scream. 10 | 11 | # v1.09: first entry changed "1 3" to "3 1" 12 | 13 | 03 01 14 | 03 02 15 | 11 10 16 | 20 22 17 | 26 27 18 | 28 0C 19 | 2F 02 20 | 30 02 21 | 2D 05 22 | 2E 04 23 | 11 29 24 | 29 0E 25 | 27 36 26 | 38 3A 27 | 3F 04 28 | 3F 05 29 | 40 04 30 | 40 05 31 | 1F 19 32 | -------------------------------------------------------------------------------- /Test/PREREPD.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: handling of rep prefixes 3 | ;--- assemble: jwasm -mz prerepd.asm 4 | 5 | .386 6 | .MODEL tiny 7 | .stack 1024 8 | .dosseg 9 | 10 | _DATA16 segment use16 public 'DATA' 11 | _DATA16 ends 12 | 13 | .code 14 | 15 | main proc c 16 | 17 | int 3 18 | ret 19 | rep movsb 20 | repnz cmpsb 21 | repz scasb 22 | repne cmpsb 23 | repe scasb 24 | 25 | assume ds:_DATA16 26 | assume es:_DATA16 27 | 28 | rep movsb [di],[si] 29 | repnz cmpsb [si],[di] 30 | repz scasb [di] 31 | repne cmpsb [si],[di] 32 | repe scasb [di] 33 | 34 | assume ds:DGROUP 35 | 36 | main endp 37 | 38 | start32 proc 39 | call main 40 | mov ax,4c00h 41 | int 21h 42 | start32 endp 43 | 44 | include initpm.inc 45 | 46 | END start 47 | 48 | -------------------------------------------------------------------------------- /Test/PRE67.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: 3 | ;---- 1. opcodes that change due to 67h prefix 4 | ;---- 2. address sizes that change due to 67h prefix 5 | ;--- assemble: jwasm -mz pre67.asm 6 | 7 | .286 8 | .MODEL small 9 | .stack 1024 10 | .dosseg 11 | .386 12 | 13 | _DATA32 segment use32 public 'DATA' 14 | _DATA32 ends 15 | 16 | .code 17 | 18 | main proc c 19 | 20 | int 3 21 | ret 22 | @@: 23 | ;--- the 32-bit variants 24 | jecxz @B 25 | loopd @B 26 | looped @B 27 | loopned @B 28 | ;--- the 16-bit variants 29 | jcxz @B 30 | loop @B 31 | loope @B 32 | loopne @B 33 | assume ds:_DATA32 34 | mov al,ds:[0] 35 | mov ax,ds:[0] 36 | mov eax,ds:[0] 37 | mov al,[esi] 38 | mov ax,[esi] 39 | mov eax,[esi] 40 | assume ds:DGROUP 41 | 42 | main endp 43 | 44 | start proc 45 | call main 46 | mov ax,4c00h 47 | int 21h 48 | start endp 49 | 50 | END start 51 | 52 | -------------------------------------------------------------------------------- /Test/PRE67D.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: 3 | ;---- 1. opcodes that change due to 67h prefix 4 | ;---- 2. address sizes that change due to 67h prefix 5 | ;--- assemble: jwasm -mz pre67d.asm 6 | 7 | .386 8 | .MODEL tiny 9 | .stack 1024 10 | .dosseg 11 | 12 | _DATA16 segment use16 public 'DATA' 13 | _DATA16 ends 14 | 15 | .code 16 | 17 | main proc c 18 | 19 | int 3 20 | ret 21 | @@: 22 | ;--- the 32-bit variants 23 | jecxz @B 24 | loopd @B 25 | looped @B 26 | loopned @B 27 | ;--- the 16-bit variants 28 | jcxz @B 29 | loopw @B 30 | loopew @B 31 | loopnew @B 32 | 33 | assume ds:_DATA16 34 | mov al,ds:[0] 35 | mov ax,ds:[0] 36 | mov eax,ds:[0] 37 | mov al,[si] 38 | mov ax,[si] 39 | mov eax,[si] 40 | assume ds:DGROUP 41 | 42 | main endp 43 | 44 | start32 proc 45 | call main 46 | mov ax,4c00h 47 | int 21h 48 | start32 endp 49 | 50 | include initpm.inc 51 | 52 | END start 53 | 54 | -------------------------------------------------------------------------------- /Test/PRE66.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: 3 | ;--- 1. opcodes that change due to 66h prefix 4 | ;--- 2. register names that change due to 66h prefix 5 | ;--- assemble: jwasm -mz pre66.asm 6 | 7 | .286 8 | .MODEL small 9 | .stack 1024 10 | .dosseg 11 | .386 12 | 13 | .data? 14 | xxx db 200 dup (?) 15 | .code 16 | 17 | main proc c 18 | 19 | int 3 20 | ret 21 | ;--- the 32-bit variants 22 | cwde 23 | cmpsd 24 | cdq 25 | fldenvd [xxx] 26 | frstord [xxx] 27 | fsaved [xxx] 28 | fstenvd [xxx] 29 | insd 30 | iretd 31 | lodsd 32 | movsd 33 | outsd 34 | popad 35 | popfd 36 | pushad 37 | pushfd 38 | retd ; should be retfd 39 | retd 4 40 | scasd 41 | stosd 42 | ;--- the 16-bit variants 43 | cbw 44 | cmpsw 45 | cwd 46 | fldenvw [xxx] 47 | frstorw [xxx] 48 | fsavew [xxx] 49 | fstenvw [xxx] 50 | insw 51 | iret ; should be iretw 52 | lodsw 53 | movsw 54 | outsw 55 | popaw 56 | popf ; should be pushfw 57 | pusha ; should be pushaw 58 | pushf ; should be pushfw 59 | retw ; should be retfw (masm 6.15 wrongly generates a 66h prefix here!) 60 | retw 4 61 | scasw 62 | stosw 63 | mov eax, 1 64 | mov ds, eax 65 | lea ebx,[bx] 66 | 67 | main endp 68 | 69 | start proc 70 | call main 71 | mov ax,4c00h 72 | int 21h 73 | start endp 74 | 75 | END start 76 | 77 | -------------------------------------------------------------------------------- /Test/PRE66D.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- disassembler: 3 | ;--- 1. opcodes that change due to 66h prefix 4 | ;--- 2. register names that change due to 66h prefix 5 | ;--- assemble: jwasm -mz pre66d.asm 6 | 7 | .386 8 | .MODEL tiny 9 | .stack 1024 10 | .dosseg 11 | 12 | .data? 13 | xxx db 200 dup (?) 14 | .code 15 | 16 | main proc c 17 | 18 | int 3 19 | ret 20 | ;--- the 32-bit variants 21 | cwde 22 | cmpsd 23 | cdq 24 | fldenvd [xxx] 25 | frstord [xxx] 26 | fsaved [xxx] 27 | fstenvd [xxx] 28 | insd 29 | iretd 30 | lodsd 31 | movsd 32 | outsd 33 | popad 34 | popfd 35 | pushad 36 | pushfd 37 | retd ; should be retfd 38 | retd 4 39 | scasd 40 | stosd 41 | ;--- the 16-bit variants 42 | cbw 43 | cmpsw 44 | cwd 45 | fldenvw [xxx] 46 | frstorw [xxx] 47 | fsavew [xxx] 48 | fstenvw [xxx] 49 | insw 50 | iret ; should be iretw 51 | lodsw 52 | movsw 53 | outsw 54 | popaw 55 | popf ; should be popfw 56 | pusha ; should be pushaw 57 | pushf ; should be pushfw 58 | retw ; should be retfw (masm 6.15 wrongly generates a 66h prefix here!) 59 | retw 4 60 | scasw 61 | stosw 62 | 63 | mov ax, 1 64 | lea bx, [bx] 65 | mov ds, ax 66 | 67 | main endp 68 | 69 | start32 proc 70 | call main 71 | mov ax,4c00h 72 | int 21h 73 | start32 endp 74 | 75 | include initpm.inc 76 | 77 | END start 78 | 79 | -------------------------------------------------------------------------------- /Test/TERM.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- test program termination with 3 | ;--- a) l cmd to reload a program 4 | ;--- b) q cmd to quit debug 5 | 6 | ;--- Vector 21h is intercepted and a breakpoint set for the AH=4Ch branch. 7 | ;--- This will return to the debugger, without actually terminating the 8 | ;--- debuggee. Prior to v2.03, debug ignored the entry mode and continued 9 | ;--- with the cmd (l/q), usually resulting in "memory corruption" or "out of 10 | ;--- memory" errors. Since v2.03, debug realizes that program termination 11 | ;--- failed and stops, reporting an "unexpected breakpoint". 12 | 13 | .286 14 | .model tiny 15 | .dosseg 16 | .stack 1024 17 | .386 18 | 19 | .data 20 | 21 | oldvec dd ? 22 | 23 | .code 24 | 25 | myint21 proc 26 | cmp ah, 4Ch 27 | jz @F 28 | jmp cs:[oldvec] 29 | @@: 30 | int 3 31 | pusha 32 | push ds 33 | lds dx, cs:[oldvec] 34 | mov ax, 2521h 35 | pushf 36 | call cs:[oldvec] 37 | pop ds 38 | popa 39 | int 21h 40 | jmp $ 41 | myint21 endp 42 | 43 | main proc 44 | 45 | mov ax, 3521h 46 | int 21h 47 | mov word ptr oldvec+0,bx 48 | mov word ptr oldvec+2,es 49 | push ds 50 | push cs 51 | pop ds 52 | mov dx, offset myint21 53 | mov ax, 2521h 54 | int 21h 55 | pop ds 56 | 57 | int 3 58 | 59 | exit: 60 | lds dx, oldvec 61 | mov ax, 2521h 62 | int 21h 63 | ret 64 | main endp 65 | 66 | start: 67 | mov ax,@data 68 | mov ds, ax 69 | mov bx, ss 70 | sub bx, ax 71 | shl bx, 4 72 | mov ss, ax 73 | add sp, bx 74 | mov bx, sp 75 | shr bx, 4 76 | add bx, 10h 77 | mov ah, 4Ah 78 | int 21h 79 | call main 80 | mov ah, 4ch 81 | int 21h 82 | 83 | END start 84 | -------------------------------------------------------------------------------- /Test/CALLJMPD.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- (dis)assembler: test 32-bit call/jmp/push [memref] 3 | ;--- create: jwasm -mz calljmpd.asm 4 | 5 | .386 6 | .MODEL tiny 7 | .stack 1024 8 | .dosseg 9 | 10 | PF16 typedef ptr far16 11 | PF32 typedef ptr far32 12 | PN32 typedef ptr near32 13 | 14 | _DATA16 segment use16 public 'DATA' 15 | var1s PN32 0 16 | var2s PF32 0 17 | var3s dw 0 18 | var4s PF16 0 19 | _DATA16 ends 20 | 21 | .code 22 | 23 | var1 dd 0 24 | var2 PF32 0 25 | var3 dw 0 26 | var4 PF16 0 27 | 28 | main proc c 29 | 30 | int 3 31 | ret 32 | 33 | call [var1] ;near32 34 | jmp [var1] 35 | call [var2] ;far32 36 | jmp [var2] 37 | call [var3] ;near16 38 | jmp [var3] 39 | call [var4] ;far16 40 | jmp [var4] 41 | call [var1][ebx] 42 | jmp [var1][ebx] 43 | call [var2][ebx] 44 | jmp [var2][ebx] 45 | call [var3][ebx] 46 | jmp [var3][ebx] 47 | call [var4][ebx] 48 | jmp [var4][ebx] 49 | 50 | push [var1] ;dword 51 | ; push [var2] 52 | push [var3] ;word 53 | push [var4] ;dword 54 | 55 | assume ds:_DATA16 56 | call [var1s] ;near32 57 | jmp [var1s] 58 | call [var2s] ;far32 59 | jmp [var2s] 60 | call [var3s] ;near16 61 | jmp [var3s] 62 | call [var4s] ;far16 63 | jmp [var4s] 64 | call [var1s][bx] 65 | jmp [var1s][bx] 66 | call [var2s][bx] 67 | jmp [var2s][bx] 68 | call [var3s][bx] 69 | jmp [var3s][bx] 70 | call [var4s][bx] 71 | jmp [var4s][bx] 72 | 73 | push [var1s] ;dword 74 | ; push [var2s] 75 | push [var3s] ;word 76 | push [var4s] ;dword 77 | assume ds:DGROUP 78 | 79 | main endp 80 | 81 | start32 proc 82 | call main 83 | mov ax,4c00h 84 | int 21h 85 | start32 endp 86 | 87 | include initpm.inc 88 | 89 | END start 90 | 91 | -------------------------------------------------------------------------------- /Test/CALLJMP.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- (dis)assembler: test 32-bit call/jmp/push [memref] 3 | ;--- create: jwasm -mz calljmp.asm 4 | 5 | .286 6 | .MODEL small 7 | .stack 1024 8 | .dosseg 9 | .386 10 | 11 | PN32 typedef ptr near32 12 | 13 | _DATA32 segment use32 public 'DATA' 14 | var1l dw 0 15 | var2l dd 0 16 | var3l PN32 0 17 | var4l df 0 18 | _DATA32 ends 19 | 20 | .data 21 | 22 | var1 dw 0 23 | var2 dd 0 24 | var3 PN32 0 25 | var4 df 0 26 | 27 | .code 28 | 29 | main proc c 30 | 31 | int 3 32 | ret 33 | 34 | call [var1] ;near16 35 | jmp [var1] 36 | call [var2] ;far16 37 | jmp [var2] 38 | call [var3] ;near32 39 | jmp [var3] 40 | call [var4] ;far32 41 | jmp [var4] 42 | call [var1][bx] 43 | jmp [var1][bx] 44 | call [var2][bx] 45 | jmp [var2][bx] 46 | call [var3][bx] 47 | jmp [var3][bx] 48 | call [var4][bx] 49 | jmp [var4][bx] 50 | 51 | push [var1] ;word 52 | push [var2] ;dword 53 | push [var3] 54 | ; push [var4] 55 | push [var1][bx];word 56 | push [var2][bx];dword 57 | push [var3][bx] 58 | ; push [var4][bx] 59 | 60 | assume ds:_DATA32 61 | call [var1l] ;near16 62 | jmp [var1l] 63 | call [var2l] ;far16 64 | jmp [var2l] 65 | call [var3l] ;near32 66 | jmp [var3l] 67 | call [var4l] ;far32 68 | jmp [var4l] 69 | call [var1l][ebx] 70 | jmp [var1l][ebx] 71 | call [var2l][ebx] 72 | jmp [var2l][ebx] 73 | call [var3l][ebx] 74 | jmp [var3l][ebx] 75 | call [var4l][ebx] 76 | jmp [var4l][ebx] 77 | 78 | push [var1l] ;word 79 | push [var2l] ;dword 80 | push [var3l] 81 | ; push [var4l] 82 | push [var1l][ebx];word 83 | push [var2l][ebx];dword 84 | push [var3l][ebx] 85 | ; push [var4l][bx] 86 | 87 | assume ds:DGROUP 88 | 89 | main endp 90 | 91 | start proc 92 | call main 93 | mov ax,4c00h 94 | int 21h 95 | start endp 96 | 97 | END start 98 | 99 | -------------------------------------------------------------------------------- /Samples/DPMICL16.SCR: -------------------------------------------------------------------------------- 1 | ; 2 | ;--- script for DEBUG/DEBUGX to generate DPMICL16.COM. 3 | ;--- to create the file enter: debug = 10000h 4 | ;--- assemble: JWasm -mz data1mb.asm 5 | 6 | LF equ 10 7 | CR equ 13 8 | 9 | .286 10 | .model small 11 | .dosseg ;this ensures that stack segment is last 12 | .stack 1024 13 | 14 | .code 15 | 16 | main proc 17 | int 3 18 | ret 19 | main endp 20 | 21 | start: 22 | mov ax, ss 23 | mov cx, es 24 | sub ax, cx 25 | mov bx, sp 26 | shr bx, 4 27 | add bx, ax 28 | mov ah, 4Ah ;free unused memory 29 | int 21h 30 | mov ax, @data 31 | mov ds, ax 32 | mov bx, ss 33 | sub bx, ax 34 | shl bx, 4 35 | mov ss, ax 36 | add sp, bx ;small model ss=ds=dgroup 37 | 38 | mov ax, 1687h ;DPMI host installed? 39 | int 2Fh 40 | and ax, ax 41 | jnz nohost 42 | push es ;save DPMI entry address 43 | push di 44 | and si, si ;requires host client-specific DOS memory? 45 | jz @F 46 | mov bx, si 47 | mov ah, 48h ;alloc DOS memory 48 | int 21h 49 | jc nomem 50 | mov es, ax 51 | @@: 52 | mov bp, sp 53 | xor ax, ax ;start a 16-bit client 54 | call far ptr [bp] ;initial switch to protected-mode 55 | jc initfailed 56 | 57 | 58 | mov cx, lowword 100000h 59 | mov bx, highword 100000h 60 | mov ax, 501h ; alloc 1 MB 61 | int 31h 62 | jc memfailed 63 | push bx 64 | push cx 65 | mov cx, 1 66 | mov ax, 0 ; alloc 1 descriptor 67 | int 31h 68 | jc descfailed 69 | mov bx, ax 70 | pop dx 71 | pop cx 72 | mov ax, 7 ; set base 73 | int 31h 74 | mov dx, lowword 100000h-1 75 | mov cx, highword 100000h-1 76 | mov ax,8 ; set descriptor limit 77 | int 31h 78 | mov cx, ds 79 | mov ss, bx ; switch SS,DS to 1 MB block 80 | mov ds, bx 81 | mov bx, cx 82 | mov ax, 1 ; free original DS descriptor 83 | int 31h 84 | call main 85 | mov ax, 4C00h 86 | int 21h 87 | 88 | starterr: 89 | nohost: 90 | call error 91 | db e1-e1 92 | nomem: 93 | call error 94 | db e2-e1 95 | initfailed: 96 | call error 97 | db e3-e1 98 | memfailed: 99 | call error 100 | db e4-e1 101 | descfailed: 102 | call error 103 | db e5-e1 104 | error: 105 | pop bx 106 | mov dl,cs:[bx] 107 | mov dh,0 108 | add dx, offset e1 109 | push cs 110 | pop ds 111 | mov ah, 9 112 | int 21h 113 | mov ax, 4C00h 114 | int 21h 115 | 116 | e1 db "no DPMI host installed",CR,LF,'$' 117 | e2 db "not enough DOS memory for initialisation",CR,LF,'$' 118 | e3 db "DPMI initialisation failed",CR,LF,'$' 119 | e4 db "no extended memory",CR,LF,'$' 120 | e5 db "no descriptors",CR,LF,'$' 121 | 122 | end start 123 | -------------------------------------------------------------------------------- /Test/TESTI2F.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- testi2f 3 | ;--- calls int 2fh, ax=1680h in protected-mode in an "endless" loop. 4 | ;--- assemble: JWasm -mz testi2f.asm 5 | 6 | LF equ 10 7 | CR equ 13 8 | 9 | .model small 10 | .386 11 | 12 | .dosseg ;this ensures that stack segment is last 13 | 14 | .stack 1024 15 | 16 | RMCS struct 17 | rEDI dd ? 18 | rESI dd ? 19 | rEBP dd ? 20 | dd ? 21 | rEBX dd ? 22 | rEDX dd ? 23 | rECX dd ? 24 | rEAX dd ? 25 | rFlags dw ? 26 | rES dw ? 27 | rDS dw ? 28 | rFS dw ? 29 | rGS dw ? 30 | rIP dw ? 31 | rCS dw ? 32 | rSP dw ? 33 | rSS dw ? 34 | RMCS ends 35 | 36 | .data 37 | 38 | .code 39 | 40 | 41 | start16: 42 | mov ax,ss 43 | mov cx,es 44 | sub ax, cx 45 | mov bx, sp 46 | shr bx, 4 47 | inc bx 48 | add bx, ax 49 | mov ah, 4Ah ;free unused memory 50 | int 21h 51 | 52 | mov ax, 1687h ;DPMI host installed? 53 | int 2Fh 54 | and ax, ax 55 | jnz nohost 56 | push es ;save DPMI entry address 57 | push di 58 | and si, si ;requires host client-specific DOS memory? 59 | jz nomemneeded 60 | mov bx, si 61 | mov ah, 48h ;alloc DOS memory 62 | int 21h 63 | jc nomem 64 | mov es, ax 65 | nomemneeded: 66 | mov ax, DGROUP 67 | mov ds, ax 68 | mov bx, ss 69 | mov bp, sp 70 | mov ax, 0001 ;start a 32-bit client 71 | call far ptr [bp] ;initial switch to protected-mode 72 | jc initfailed 73 | 74 | ;--- now in protected-mode 75 | 76 | sub sp, sizeof RMCS+2 77 | movzx ebp, sp 78 | push ss 79 | pop es 80 | @@: 81 | xor eax, eax 82 | mov [bp].RMCS.rSP, ax 83 | mov [bp].RMCS.rSS, ax 84 | mov word ptr [bp].RMCS.rFlags, 203h 85 | mov word ptr [bp].RMCS.rEAX, 1680h 86 | mov bx, 002Fh 87 | xor cx,cx 88 | mov edi,ebp 89 | mov ax,0300h ;temporarily switch to real-mode 90 | int 31h 91 | mov ah,02 92 | mov dl,'.' 93 | int 21h 94 | jmp @B 95 | 96 | mov ax,4c00h 97 | int 21h 98 | 99 | nohost: 100 | mov dx, offset dErr1 101 | jmp error 102 | nomem: 103 | mov dx, offset dErr2 104 | jmp error 105 | initfailed: 106 | mov dx, offset dErr3 107 | error: 108 | push cs 109 | pop ds 110 | mov ah, 9 111 | int 21h 112 | mov ax, 4C00h 113 | int 21h 114 | 115 | dErr1 db "no DPMI host installed",CR,LF,'$' 116 | dErr2 db "not enough DOS memory for initialisation",CR,LF,'$' 117 | dErr3 db "DPMI initialisation failed",CR,LF,'$' 118 | dBackinRM db "switched to real-mode",CR,LF,'$' 119 | 120 | _TEXT16 ends 121 | 122 | end start16 123 | -------------------------------------------------------------------------------- /Test/LEAVE.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- test LEAVE instruction in protected-mode 3 | 4 | ;--- the leave instruction may cause stack exceptions 5 | ;--- if 16-bit code runs as 32-bit DPMI client. 6 | 7 | .286 8 | .MODEL small 9 | option casemap:none 10 | .dosseg 11 | .stack 2048 12 | 13 | .code 14 | 15 | ;--- little procedure that does a 16-bit multiplication, result returned in DX:AX. 16 | ;--- problem is that the ret instruction may cause the assembler to add a LEAVE 17 | ;--- instruction, and there's also a slight incompatibility if jwasm is used 18 | ;--- without option -Zg: 19 | ;--- 20 | ;--- .286 .386 .486 .586 21 | ;-------------------------------------- 22 | ;--- Masm y n n y ( y = LEAVE generated ) 23 | ;--- JWasm y y n n 24 | ;--- JWasm(-Zg) y n n y 25 | 26 | mul16 proc c p1:word, p2:word 27 | mov ax,p1 28 | mul p2 29 | ret 30 | mul16 endp 31 | 32 | .386 33 | 34 | main proc c 35 | 36 | mov ebp, 12345678h ; if hiword(ebp) is != 0, LEAVE will cause a stack exception 37 | ; mov ebp, 5678h ; if hiword(ebp) == 0, program runs without problems 38 | invoke mul16, 2, 2 39 | ret 40 | main endp 41 | 42 | start proc c public 43 | 44 | ;--- setup small memory model 45 | 46 | cld 47 | mov dx, @data 48 | mov ds, dx 49 | mov ax, ss 50 | sub ax, dx 51 | shl ax, 4 52 | mov ss, dx 53 | add sp, ax 54 | 55 | ;--- now ds=ss=dgroup 56 | 57 | mov bx, sp 58 | shr bx, 4 59 | mov cx, es 60 | mov ax, ss 61 | sub ax, cx 62 | add bx, ax 63 | mov ah, 4Ah ;free unused memory 64 | int 21h 65 | mov ax, 1687h ;DPMI host installed? 66 | int 2Fh 67 | and ax, ax 68 | jnz nohost 69 | push es ;save DPMI entry address 70 | push di 71 | and si, si ;requires host client-specific DOS memory? 72 | jz nomemneeded 73 | mov bx, si 74 | mov ah, 48h ;alloc DOS memory 75 | int 21h 76 | jc nomem 77 | mov es, ax 78 | nomemneeded: 79 | mov bp, sp 80 | mov ax, 1 ;start a 16-bit client 81 | call far ptr [bp] 82 | jc initfailed 83 | add sp,4 84 | call main 85 | mov ah, 4Ch 86 | int 21h 87 | nohost: 88 | call error 89 | db "no DPMI host installed",13,10,'$' 90 | nomem: 91 | call error 92 | db "not enough DOS memory for initialisation",13,10,'$' 93 | initfailed: 94 | call error 95 | db "DPMI initialisation failed",13,10,'$' 96 | error: 97 | push cs 98 | pop ds 99 | pop dx 100 | mov ah, 9 101 | int 21h 102 | mov ax, 4C00h 103 | int 21h 104 | 105 | start endp 106 | 107 | END start 108 | 109 | -------------------------------------------------------------------------------- /Samples/DPMICL32.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- DPMICL32.ASM: 32bit DPMI application written in MASM syntax. 3 | ;--- assemble: JWasm -mz dpmicl32.asm 4 | 5 | LF equ 10 6 | CR equ 13 7 | 8 | .386 9 | .model small 10 | 11 | .dosseg ;this ensures that stack segment is last 12 | 13 | .stack 1024 14 | 15 | .data 16 | 17 | szWelcome db "welcome in protected-mode",CR,LF,0 18 | 19 | .code 20 | 21 | start: 22 | mov esi, offset szWelcome 23 | call printstring 24 | mov ax, 4C00h ;normal client exit 25 | int 21h 26 | 27 | ;--- print a string in protected-mode with simple 28 | ;--- DOS commands not using pointers. 29 | 30 | printstring: 31 | lodsb 32 | and al,al 33 | jz stringdone 34 | mov dl,al 35 | mov ah,2 36 | int 21h 37 | jmp printstring 38 | stringdone: 39 | ret 40 | 41 | ;--- now comes the 16bit initialization part 42 | 43 | _TEXT16 segment use16 word public 'CODE' 44 | 45 | start16: 46 | mov ax,ss 47 | mov cx,es 48 | sub ax, cx 49 | mov bx, sp 50 | shr bx, 4 51 | inc bx 52 | add bx, ax 53 | mov ah, 4Ah ;free unused memory 54 | int 21h 55 | 56 | mov ax, 1687h ;DPMI host installed? 57 | int 2Fh 58 | and ax, ax 59 | jnz nohost 60 | push es ;save DPMI entry address 61 | push di 62 | and si, si ;requires host client-specific DOS memory? 63 | jz nomemneeded 64 | mov bx, si 65 | mov ah, 48h ;alloc DOS memory 66 | int 21h 67 | jc nomem 68 | mov es, ax 69 | nomemneeded: 70 | mov ax, DGROUP 71 | mov ds, ax 72 | mov bp, sp 73 | mov ax, 0001 ;start a 32-bit client 74 | call far ptr [bp] ;initial switch to protected-mode 75 | jc initfailed 76 | 77 | ;--- now in protected-mode 78 | 79 | ;--- create a 32bit code selector and jump to 32bit code 80 | 81 | mov cx,1 82 | mov ax,0 83 | int 31h 84 | mov bx,ax 85 | mov cx,_TEXT 86 | mov dx,cx 87 | shl dx,4 88 | shr cx,12 89 | mov ax,7 90 | int 31h ;set base address 91 | mov dx,-1 92 | mov cx,0 93 | mov ax,8 94 | int 31h ;set descriptor limit to 64 kB 95 | mov cx,cs 96 | lar cx,cx 97 | shr cx,8 98 | or ch,40h 99 | mov ax,9 100 | int 31h ;set code descriptors attributes to 32bit 101 | push ebx 102 | push offset start 103 | retd ;jump to 32-bit code 104 | 105 | nohost: 106 | mov dx, offset dErr1 107 | jmp error 108 | nomem: 109 | mov dx, offset dErr2 110 | jmp error 111 | initfailed: 112 | mov dx, offset dErr3 113 | error: 114 | push cs 115 | pop ds 116 | mov ah, 9 117 | int 21h 118 | mov ax, 4C00h 119 | int 21h 120 | 121 | dErr1 db "no DPMI host installed",CR,LF,'$' 122 | dErr2 db "not enough DOS memory for initialisation",CR,LF,'$' 123 | dErr3 db "DPMI initialisation failed",CR,LF,'$' 124 | 125 | _TEXT16 ends 126 | 127 | end start16 128 | -------------------------------------------------------------------------------- /Test/CODETS32.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- CODETS32.ASM: 32-bit DPMI app with 32-bit code offsets > 0ffffh. 3 | ;--- assemble: JWasm -mz codets32.asm 4 | 5 | LF equ 10 6 | CR equ 13 7 | 8 | .386 9 | .model small 10 | 11 | .dosseg ;this ensures that stack segment is last 12 | 13 | .stack 1024 14 | 15 | .data 16 | 17 | szWelcome db "welcome in protected-mode",CR,LF,0 18 | 19 | .code 20 | 21 | db 10000h dup (0) ;ensure offsets are > 0ffffh 22 | 23 | start: 24 | mov esi, offset szWelcome 25 | call printstring 26 | mov ax, 4C00h ;normal client exit 27 | int 21h 28 | 29 | ;--- print a string in protected-mode with simple 30 | ;--- DOS commands not using pointers. 31 | 32 | printstring: 33 | lodsb 34 | and al,al 35 | jz stringdone 36 | mov dl,al 37 | mov ah,2 38 | int 21h 39 | jmp printstring 40 | stringdone: 41 | ret 42 | 43 | ;--- now comes the 16bit initialization part 44 | 45 | _TEXT16 segment use16 word public 'CODE' 46 | 47 | start16: 48 | mov ax,ss 49 | mov cx,es 50 | sub ax, cx 51 | mov bx, sp 52 | shr bx, 4 53 | inc bx 54 | add bx, ax 55 | mov ah, 4Ah ;free unused memory 56 | int 21h 57 | 58 | mov ax, 1687h ;DPMI host installed? 59 | int 2Fh 60 | and ax, ax 61 | jnz nohost 62 | push es ;save DPMI entry address 63 | push di 64 | and si, si ;requires host client-specific DOS memory? 65 | jz nomemneeded 66 | mov bx, si 67 | mov ah, 48h ;alloc DOS memory 68 | int 21h 69 | jc nomem 70 | mov es, ax 71 | nomemneeded: 72 | mov ax, DGROUP 73 | mov ds, ax 74 | mov bp, sp 75 | mov ax, 0001 ;start a 32-bit client 76 | call far ptr [bp] ;initial switch to protected-mode 77 | jc initfailed 78 | 79 | ;--- now in protected-mode 80 | 81 | ;--- create a 32bit code selector and jump to 32bit code 82 | 83 | mov cx,1 84 | mov ax,0 85 | int 31h 86 | mov bx,ax 87 | mov cx,_TEXT 88 | mov dx,cx 89 | shl dx,4 90 | shr cx,12 91 | mov ax,7 92 | int 31h ;set base address 93 | mov dx,-1 94 | mov cx,dx 95 | mov ax,8 96 | int 31h ;set descriptor limit 97 | mov cx,cs 98 | lar cx,cx 99 | shr cx,8 100 | or ch,40h 101 | mov ax,9 102 | int 31h ;set code descriptors attributes to 32bit 103 | push ebx 104 | push offset start 105 | retd ;jump to 32-bit code 106 | 107 | nohost: 108 | mov dx, offset dErr1 109 | jmp error 110 | nomem: 111 | mov dx, offset dErr2 112 | jmp error 113 | initfailed: 114 | mov dx, offset dErr3 115 | error: 116 | push cs 117 | pop ds 118 | mov ah, 9 119 | int 21h 120 | mov ax, 4C00h 121 | int 21h 122 | 123 | dErr1 db "no DPMI host installed",CR,LF,'$' 124 | dErr2 db "not enough DOS memory for initialisation",CR,LF,'$' 125 | dErr3 db "DPMI initialisation failed",CR,LF,'$' 126 | 127 | _TEXT16 ends 128 | 129 | end start16 130 | -------------------------------------------------------------------------------- /Test/DBGMBR.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- simple MBR showing how DebugB may be invoked. 3 | 4 | ;--- 1. the MBR is loaded by the BIOS at 0000:7C00 5 | ;--- 2. it relocates itself to 0000:0600 6 | ;--- 3. reads 40 sectors (# 1-40 ) at 0800:0000 7 | ;--- 4. calls 0800h:0000 8 | ;--- 5. runs an INT 3 to activate debugger 9 | 10 | ;--- To continue from inside the debugger, use the DP and L commands to 11 | ;--- select and load a partition boot sector ( at address 0000:7C00 ). 12 | ;--- After that, set register IP to 7C00h and G(o). 13 | 14 | _TEXT segment word public 'CODE' 15 | 16 | assume ds:_TEXT 17 | 18 | org 600h 19 | 20 | start: 21 | XOR AX, AX 22 | MOV SS, AX 23 | MOV SP, 7C00h 24 | STI 25 | mov es, ax 26 | mov ds, ax 27 | CLD 28 | MOV SI, offset start2 + (7C00h - 600h) 29 | MOV DI, offset start2 30 | PUSH AX 31 | PUSH DI 32 | MOV CX, (start+200h) - start2 33 | REP MOVSB 34 | RETF 35 | start2: 36 | 37 | ;--- no check of partition table, just load DebugB ( assumed in sector 1 - 4x ) 38 | ;--- register DL should contain disk# 39 | 40 | push dx ; save drive [bp+6] 41 | MOV BX, 55AAh 42 | MOV AH, 41h 43 | INT 13h 44 | JB nolba 45 | CMP BX, 0AA55h 46 | JNZ nolba 47 | TEST CL, 01 48 | JZ nolba 49 | mov ax, 1 50 | jmp ok 51 | nolba: 52 | mov ah, 8 53 | int 13h 54 | jc error1 55 | mov si, cx 56 | and si, 3Fh 57 | mov al, dh 58 | inc al 59 | mov ah, 0 60 | mov di, ax 61 | mov ax, 0 62 | ok: 63 | push ax ; access method: 0=chs,1=lba [bp+4] 64 | mov ax, 0 65 | push ax ; hiword sector# [bp+2] 66 | mov ax, 1 67 | push ax ; loword sector# [bp+0] 68 | mov bp, sp 69 | mov cx, 40 ; sectors to read 70 | mov bx, 8000h ; offset of address to load DebugB 71 | call read_access 72 | jc error1 73 | db 9ah ; call 0800h:0000 74 | dw 0, 800h 75 | mov dx,[bp+6] 76 | int 3 77 | int 19h 78 | 79 | lba2chs: 80 | mov cx, word ptr [bp+0] 81 | mov ax, word ptr [bp+2] 82 | xor dx, dx 83 | div si 84 | xchg ax, cx 85 | div si 86 | inc dx 87 | xchg cx, dx 88 | div di 89 | mov dh, dl 90 | mov ch, al 91 | ror ah, 1 92 | ror ah, 1 93 | or cl, ah 94 | ret 95 | 96 | ;--- read cx sectors at es:bx 97 | ;--- sector# in [bp+0], access method in [bp+4], drive in [bp+6] 98 | 99 | read_access: 100 | cmp word ptr [bp+4],0 101 | jnz uselba 102 | push cx 103 | call lba2chs ; translate LBA to CHS (DH:CX) 104 | pop ax ; sectors to read in AL 105 | mov dl, [bp+6] 106 | MOV AH, 2h ; CHS read 107 | INT 13h 108 | ret 109 | uselba: 110 | XOR SI,SI 111 | PUSH SI ; sector# 48-63 112 | PUSH SI ; sector# 32-47 113 | PUSH word ptr [bp+2] 114 | PUSH word ptr [bp+0] 115 | PUSH ES 116 | PUSH BX 117 | PUSH CX 118 | MOV SI,0010h 119 | PUSH SI 120 | MOV SI,SP 121 | mov dl, [bp+6] 122 | MOV AX,4200h ; LBA read 123 | INT 13h 124 | lea sp, [si+2*8] 125 | RET 126 | 127 | error1: 128 | mov si, offset szerr 129 | nextchar: 130 | lodsb 131 | and al,al 132 | jz @F 133 | mov ah,0eh 134 | mov bx,1 135 | int 10h 136 | jmp nextchar 137 | @@: 138 | int 18h 139 | jmp @B 140 | 141 | szerr db "disk i/o error",13,10,0 142 | 143 | org 7feh 144 | dw 0AA55h 145 | 146 | _TEXT ends 147 | 148 | end 149 | -------------------------------------------------------------------------------- /Samples/DPMIBK16.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- DPMIBK16.ASM: 16bit DPMI application written in MASM syntax. 3 | ;--- this sample temporarily switches back to real-mode. 4 | ;--- assemble: JWasm -bin -Fo dpmibk16.com dpmibk16.asm 5 | 6 | LF equ 10 7 | CR equ 13 8 | 9 | .286 10 | .model tiny 11 | 12 | ;--- DPMI real-mode call structure 13 | 14 | RMCS struct 15 | rEDI dd ? 16 | rESI dd ? 17 | rEBP dd ? 18 | dd ? 19 | rEBX dd ? 20 | rEDX dd ? 21 | rECX dd ? 22 | rEAX dd ? 23 | rFlags dw ? 24 | rES dw ? 25 | rDS dw ? 26 | rFS dw ? 27 | rGS dw ? 28 | rIP dw ? 29 | rCS dw ? 30 | rSP dw ? 31 | rSS dw ? 32 | RMCS ends 33 | 34 | .code 35 | 36 | org 100h 37 | 38 | ;--- the 16bit initialization part 39 | 40 | start: 41 | pop ax ;get word saved on stack for COM files 42 | mov bx, sp 43 | shr bx, 4 44 | jnz @F 45 | mov bx,1000h ;it was a full 64kB stack 46 | @@: 47 | mov ah, 4Ah ;free unused memory 48 | int 21h 49 | mov ax, 1687h ;DPMI host installed? 50 | int 2Fh 51 | and ax, ax 52 | jnz nohost 53 | push es ;save DPMI entry address 54 | push di 55 | and si, si ;requires host client-specific DOS memory? 56 | jz nomemneeded 57 | mov bx, si 58 | mov ah, 48h ;alloc DOS memory 59 | int 21h 60 | jc nomem 61 | mov es, ax 62 | nomemneeded: 63 | mov bp, sp 64 | mov bx, cs ;save real-mode value of CS in BX 65 | mov ax, 0000 ;start a 16-bit client 66 | call far ptr [bp] ;initial switch to protected-mode 67 | jnc initok 68 | call error 69 | db "DPMI initialisation failed",CR,LF,'$' 70 | nohost: 71 | call error 72 | db "no DPMI host installed",CR,LF,'$' 73 | nomem: 74 | call error 75 | db "not enough DOS memory for initialisation",CR,LF,'$' 76 | error: 77 | push cs 78 | pop ds 79 | pop dx 80 | mov ah, 9 81 | int 21h 82 | mov ax, 4C00h 83 | int 21h 84 | 85 | ;--- now in protected-mode 86 | 87 | initok: 88 | push bx 89 | call printstring 90 | db "welcome in protected-mode",CR,LF,0 91 | pop bx 92 | 93 | ;--- switch back to real-mode 94 | 95 | sub sp, sizeof RMCS 96 | mov bp,sp 97 | mov [bp].RMCS.rIP, offset backinreal 98 | mov [bp].RMCS.rCS, bx 99 | xor ax, ax 100 | mov [bp].RMCS.rFlags, ax 101 | mov [bp].RMCS.rDS, ax 102 | mov [bp].RMCS.rES, ax 103 | lea ax,[bp-20h] 104 | mov [bp].RMCS.rSP, ax 105 | mov [bp].RMCS.rSS, bx 106 | xor bx,bx 107 | xor cx,cx 108 | mov di,bp 109 | push ss 110 | pop es 111 | mov ax,0301h ;temporarily switch to real-mode 112 | int 31h 113 | 114 | call printstring 115 | db "back in protected-mode",CR,LF,0 116 | mov ax, 4C00h ;normal client exit 117 | int 21h 118 | 119 | backinreal: 120 | push cs 121 | pop ds 122 | call printstring 123 | db "switched to real-mode",CR,LF,0 124 | retf ;back to protected-mode 125 | 126 | ;--- print a string in both protected-mode and real-mode. 127 | ;--- uses simple DOS commands without pointers. 128 | 129 | printstring: 130 | pop si 131 | nextchar: 132 | lodsb 133 | and al,al 134 | jz stringdone 135 | mov dl,al 136 | mov ah,2 137 | int 21h 138 | jmp nextchar 139 | stringdone: 140 | push si 141 | ret 142 | 143 | end start 144 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # create all DEBUG versions with JWasm. 3 | # Masm could also be used, but then an OMF linker is required; 4 | # also, Masm won't be able to assemble the long mode variant DEBUGRL.BIN. 5 | 6 | # to enable the BP/BC cmds, use -DBCMD=1 7 | 8 | NAME=DEBUG 9 | OUTD=build 10 | 11 | ALL: $(OUTD)/DEBUG.COM $(OUTD)/DEBUGX.COM $(OUTD)/DEBUGXD.COM $(OUTD)/DEBUGXE.COM $(OUTD)/DEBUGXF.COM \ 12 | $(OUTD)/DEBUGXG.EXE $(OUTD)/DEBUGXU.COM $(OUTD)/DEBUGXV.COM $(OUTD)/DEBUGB.BIN $(OUTD)/DEBUGR.BIN $(OUTD)/DEBUGRL.BIN $(OUTD)/DEBUGRV.BIN 13 | 14 | DEPS= src/$(NAME).ASM src/ASMTBL.INC src/DISTBL.INC src/DPRINTF.INC src/FPTOSTR.INC src/DISASM.INC src/LINEASM.INC 15 | 16 | $(OUTD)/DEBUG.COM: $(DEPS) src/TRAPR.INC 17 | @echo creating debug.com 18 | @jwasm -nologo -bin -Fo$(OUTD)/DEBUG.COM -Fl$(OUTD)/DEBUG.LST src/$(NAME).ASM 19 | $(OUTD)/DEBUGX.COM: $(DEPS) src/TRAPR.INC src/TRAPD.INC 20 | @echo creating debugx.com 21 | @jwasm -nologo -D?DPMI=1 -DALTVID=1 -bin -Fo $(OUTD)/DEBUGX.COM -Fl$(OUTD)/DEBUGX.LST src/$(NAME).ASM 22 | $(OUTD)/DEBUGXD.COM: $(DEPS) src/TRAPR.INC src/TRAPD.INC 23 | @echo creating debugxD - debug version of debugx 24 | @jwasm -nologo -D?DPMI=1 -bin -Fo $(OUTD)/DEBUGXD.COM -Fl=$(OUTD)/DEBUGXD.LST -DCATCHINT01=0 -DCATCHINT03=0 -DPROMPT=] src/$(NAME).ASM 25 | $(OUTD)/DEBUGXE.COM: $(DEPS) src/TRAPR.INC src/TRAPD.INC 26 | @echo creating debugxE - checks for exc 06, 0C and 0D in real-mode 27 | @jwasm -nologo -D?DPMI=1 -bin -Fo $(OUTD)/DEBUGXE.COM -Fl=$(OUTD)/DEBUGXE.LST -DCATCHINT06=1 -DCATCHINT0C=1 -DCATCHINT0D=1 src/$(NAME).ASM 28 | $(OUTD)/DEBUGXF.COM: $(DEPS) src/TRAPR.INC src/TRAPD.INC 29 | @echo creating debugxF - debugger handles exc 0,1,3, 0d and 0e in protected-mode exclusively 30 | @jwasm -nologo -D?DPMI=1 -bin -Fo $(OUTD)/DEBUGXF.COM -Fl=$(OUTD)/DEBUGXF.LST -DCATCHINT31=1 src/$(NAME).ASM 31 | $(OUTD)/DEBUGXG.EXE: $(DEPS) src/TRAPR.INC src/TRAPD.INC 32 | @echo creating debugxG - device driver version of debugx, b cmds 33 | @jwasm -nologo -D?DPMI=1 -mz -Fo $(OUTD)/DEBUGXG.EXE -Fl=$(OUTD)/DEBUGXG.LST -DDRIVER=1 -DBCMD=1 src/$(NAME).ASM 34 | $(OUTD)/DEBUGXU.COM: $(DEPS) src/TRAPR.INC src/TRAPD.INC 35 | @echo creating debugxU - dx cmd uses unreal mode 36 | @jwasm -nologo -D?DPMI=1 -bin -Fo $(OUTD)/DEBUGXU.COM -Fl=$(OUTD)/DEBUGXU.LST -DUSEUNREAL=1 -DCATCHINT0D=1 src/$(NAME).ASM 37 | $(OUTD)/DEBUGXV.COM: $(DEPS) src/TRAPR.INC src/TRAPD.INC 38 | @echo creating debugxV - v cmd flips screens, sysreq trapped, b cmds 39 | @jwasm -nologo -D?DPMI=1 -bin -Fo $(OUTD)/DEBUGXV.COM -Fl=$(OUTD)/DEBUGXV.LST -DVXCHG=1 -DCATCHSYSREQ=1 -DBCMD=1 src/$(NAME).ASM 40 | $(OUTD)/DEBUGB.BIN: $(DEPS) src/TRAPR.INC 41 | @echo creating debugB.bin - a "boot loader" version 42 | @jwasm -nologo -bin -Fo $(OUTD)/DEBUGB.BIN -Fl=$(OUTD)/DEBUGB.LST -DBOOTDBG=1 -DBCMD=1 src/$(NAME).ASM 43 | $(OUTD)/DEBUGR.BIN: $(DEPS) src/TRAPP.INC 44 | @echo creating debugR.bin - a protected-mode "ring 0" version 45 | @jwasm -nologo -bin -Fo $(OUTD)/DEBUGR.BIN -Fl=$(OUTD)/DEBUGR.LST -DRING0=1 src/$(NAME).ASM 46 | $(OUTD)/DEBUGRL.BIN: $(DEPS) src/TRAPPL.INC 47 | @echo creating debugRL.bin - a protected-mode "ring 0" version for long mode 48 | @jwasm -nologo -bin -Fo $(OUTD)/DEBUGRL.BIN -Fl=$(OUTD)/DEBUGRL.LST -Sg -DRING0=1 -DLMODE=1 src/$(NAME).ASM 49 | $(OUTD)/DEBUGRV.BIN: $(DEPS) src/TRAPPV.INC 50 | @echo creating debugRV.bin - a protected-mode "ring 0" version with v86 support 51 | @jwasm -nologo -bin -Fo $(OUTD)/DEBUGRV.BIN -Fl=$(OUTD)/DEBUGRV.LST -Sg -DRING0=1 -DV86M=1 -DCATCHSYSREQ=1 -DCATCHINT0C=1 src/$(NAME).ASM 52 | 53 | clean: 54 | del $(OUTD)\$(NAME)*.com 55 | del $(OUTD)\DEBUGXG.exe 56 | del $(OUTD)\$(NAME)*.bin 57 | del $(OUTD)\$(NAME)*.lst 58 | -------------------------------------------------------------------------------- /Test/TESTQQ.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- test debugx's qq cmd ( new since v1.29 ). 3 | 4 | ;--- this little test program is buggy. 5 | ;--- it intercepts int 21h in protected-mode, and 6 | ;--- firmly assumes that register DS holds a selector 7 | ;--- for DGROUP when an int 21h is called. After DS is set to NULL, 8 | ;--- a 'q' command inside DEBUGX fails, protected-mode cannot be left. 9 | ;--- since v1.29 there's now a "qq" command, which resets pm int 21h. 10 | ;--- "qq" will terminate the debuggee, and debugx's real-mode prompt '-' 11 | ;--- should appear. 12 | 13 | .286 14 | .MODEL small 15 | option casemap:none 16 | .dosseg 17 | .stack 2048 18 | .386 19 | 20 | .data 21 | 22 | oldint21 dd 0 23 | 24 | .code 25 | 26 | ;--- the client's int 21h routine 27 | ;--- if firmly assumes that register ds holds selector for dgroup! 28 | 29 | myint21 proc 30 | cmp ah, 9 31 | jz is09 32 | jmp [oldint21] 33 | is09: 34 | pushd 0 ; set SS:SP to 0:0 35 | sub sp, 2*2 ; skip CS:IP 36 | push 0 ; gs 37 | push 0 ; fs 38 | push @data ; ds=real-mode DGROUP 39 | push @data ; es=real-mode DGROUP 40 | pushf 41 | pushad 42 | mov di, sp ; now ss:sp -> DPMI RMCS 43 | push ss 44 | pop es 45 | mov bx, 0021h 46 | xor cx, cx 47 | mov ax, 0300h 48 | int 31h 49 | popad 50 | popf 51 | add sp, 8*2 52 | iret 53 | 54 | myint21 endp 55 | 56 | main proc c 57 | 58 | .const 59 | string1 db "hello, debugx",13,10,'$' 60 | .code 61 | 62 | mov dx, offset string1 63 | mov ah, 9 64 | int 21h 65 | push 0 ; now set DS != DGROUP; makes calling int 21h "impossible" 66 | pop ds 67 | ret 68 | main endp 69 | 70 | 71 | start proc c public 72 | 73 | ;--- setup small memory model 74 | 75 | cld 76 | mov dx, @data 77 | mov ds, dx 78 | mov ax, ss 79 | sub ax, dx 80 | shl ax, 4 81 | mov ss, dx 82 | add sp, ax 83 | 84 | ;--- now ds=ss=dgroup 85 | 86 | mov bx, sp 87 | shr bx, 4 88 | mov cx, es 89 | mov ax, ss 90 | sub ax, cx 91 | add bx, ax 92 | mov ah, 4Ah ;free unused memory 93 | int 21h 94 | mov ax, 1687h ;DPMI host installed? 95 | int 2Fh 96 | and ax, ax 97 | jnz nohost 98 | push es ;save DPMI entry address 99 | push di 100 | and si, si ;requires host client-specific DOS memory? 101 | jz nomemneeded 102 | mov bx, si 103 | mov ah, 48h ;alloc DOS memory 104 | int 21h 105 | jc nomem 106 | mov es, ax 107 | nomemneeded: 108 | mov bp, sp 109 | mov ax, 0000 ;start a 16-bit client 110 | call far ptr [bp] 111 | jc initfailed 112 | 113 | ;--- intercept protected-mode int 21h 114 | 115 | mov bl,21h 116 | mov ax,0204h 117 | int 31h 118 | mov word ptr [oldint21+0],dx 119 | mov word ptr [oldint21+2],cx 120 | mov cx, cs 121 | mov dx, offset myint21 122 | mov al,5 123 | int 31h 124 | call main 125 | mov ax, 4C00h 126 | int 21h 127 | nohost: 128 | call error 129 | db "no DPMI host installed",13,10,'$' 130 | nomem: 131 | call error 132 | db "not enough DOS memory for initialisation",13,10,'$' 133 | initfailed: 134 | call error 135 | db "DPMI initialisation failed",13,10,'$' 136 | error: 137 | push cs 138 | pop ds 139 | pop dx 140 | mov ah, 9 141 | int 21h 142 | mov ax, 4C00h 143 | int 21h 144 | 145 | start endp 146 | 147 | END start 148 | 149 | -------------------------------------------------------------------------------- /Test/UNREAL.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- test unreal mode and 3 | ;--- DX command of debugxu.com 4 | 5 | .model small 6 | .dosseg 7 | option casemap:none 8 | .stack 5120 9 | 10 | DGROUP group _TEXT ;makes a tiny model 11 | 12 | CStr macro text:vararg 13 | local sym 14 | .const 15 | sym db text,0 16 | .code 17 | exitm 18 | endm 19 | 20 | .data 21 | 22 | SEL_FLAT equ 1*8 23 | SEL_DATA16 equ 2*8 24 | 25 | GDT dq 0 ; null descriptor 26 | dw 0FFFFh,0,9200h,0CFh ; 32-bit flat data descriptor 27 | dw 0FFFFh,0,9200h,0h ; 16-bit data descriptor 28 | 29 | GDTR label fword ; Global Descriptors Table Register 30 | dw 3*8-1 ; limit of GDT (size minus one) 31 | dd 0 ; linear address of GDT 32 | 33 | .code 34 | 35 | .386 36 | assume DS:DGROUP 37 | 38 | myint0d1 proc 39 | push cs 40 | pop ds 41 | mov dx,CStr(<"unexpected exception occured",13,10,'$'>) 42 | mov ah,9 43 | int 21h 44 | add sp,4 45 | popf 46 | jmp continue1 47 | myint0d1 endp 48 | 49 | myint0d2 proc 50 | push cs 51 | pop ds 52 | mov dx,CStr(<"expected exception occured",13,10,'$'>) 53 | mov ah,9 54 | int 21h 55 | add sp,4 56 | popf 57 | jmp continue2 58 | myint0d2 endp 59 | 60 | ;--- 16bit start/exit code 61 | 62 | start16 proc 63 | 64 | push cs 65 | pop ds 66 | mov ax,ss 67 | mov dx,es 68 | sub ax,dx 69 | mov bx,sp 70 | shr bx,4 71 | add bx,ax 72 | mov ax,bx 73 | sub ax,10h 74 | shl ax,4 75 | push ds 76 | pop ss 77 | mov sp,ax ; make a TINY model, CS=SS=DS 78 | mov ah,4Ah 79 | int 21h ; free unused memory 80 | 81 | smsw ax 82 | test ax,1 83 | jz @F 84 | mov dx,CStr(<"will run in real-mode only",13,10,'$'>) 85 | mov ah,9 86 | int 21h 87 | jmp exit 88 | @@: 89 | mov ax,ds 90 | movzx eax,ax 91 | shl eax,4 92 | add eax,offset GDT 93 | mov dword ptr [GDTR+2], eax ; convert offset to linear address 94 | 95 | xor ax,ax 96 | mov es,ax 97 | mov edi,es:[0dh*4] 98 | 99 | int 3 100 | call EnableUnreal 101 | 102 | mov ax,cs 103 | shl eax,16 104 | mov ax,offset myint0d1 105 | mov es:[0dh*4],eax 106 | 107 | 108 | xor ax,ax 109 | mov ds,ax 110 | mov ecx,100000h 111 | mov ax,ds:[ecx] 112 | continue1:: 113 | push cs 114 | pop ds 115 | call DisableUnreal 116 | 117 | mov ax,cs 118 | shl eax,16 119 | mov ax,offset myint0d2 120 | mov es:[0dh*4],eax 121 | 122 | xor ax,ax 123 | mov ds,ax 124 | mov ecx,100000h 125 | mov ax,ds:[ecx] 126 | continue2:: 127 | mov es:[0dh*4],edi 128 | push cs 129 | pop ds 130 | exit: 131 | mov ax,4c00h 132 | int 21h 133 | start16 endp 134 | 135 | .386p 136 | 137 | EnableUnreal proc 138 | cli 139 | push ds 140 | lgdt [GDTR] 141 | mov eax,cr0 142 | or al,1 143 | mov cr0,eax 144 | jmp @F 145 | @@: 146 | mov bx,ds 147 | mov bx,SEL_FLAT 148 | mov ds,bx 149 | and al,0FEh 150 | mov cr0,eax 151 | jmp @F 152 | @@: 153 | pop ds 154 | sti 155 | ret 156 | EnableUnreal endp 157 | 158 | DisableUnreal proc 159 | cli 160 | lgdt cs:[GDTR] 161 | push ds 162 | mov eax,cr0 163 | inc ax 164 | mov cr0,eax 165 | jmp @F 166 | @@: 167 | mov bx,SEL_DATA16 168 | mov ds,bx 169 | dec ax 170 | mov cr0,eax 171 | jmp @F 172 | @@: 173 | pop ds 174 | sti 175 | ret 176 | DisableUnreal endp 177 | 178 | end start16 179 | -------------------------------------------------------------------------------- /Test/HUGESEG.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- HUGESEG.ASM: 32bit DPMI application. 3 | ;--- assemble: JWasm -mz hugeseg.asm 4 | ;--- this sample is to test debugx's correct handling of 32-bit offsets 5 | ;--- for the a/c/d/e/m/s/u commands. 6 | 7 | LF equ 10 8 | CR equ 13 9 | 10 | MEMSIZE equ 200000h 11 | 12 | .386 13 | .model small 14 | 15 | .dosseg ;this ensures that stack segment is last 16 | 17 | .stack 1024 18 | 19 | .data 20 | 21 | .code 22 | 23 | start: 24 | mov bx, highword MEMSIZE 25 | mov cx, lowword MEMSIZE 26 | mov ax, 501h ;allocate a 128 kb block 27 | int 31h 28 | jc errx 29 | ;--- bx:cx contains the address of the block 30 | push bx 31 | push cx 32 | mov cx,1 33 | mov ax,0 ;allocate a descriptor 34 | int 31h 35 | jc errx 36 | mov bx,ax 37 | pop dx 38 | pop cx 39 | mov ax,7 ;set base of descriptor 40 | int 31h 41 | jc errx 42 | mov cx,highword (MEMSIZE-1) 43 | mov dx,lowword (MEMSIZE-1) 44 | mov ax,8 ;set limit of descriptor 45 | int 31h 46 | jc errx 47 | mov ds,bx 48 | 49 | ;--- now we have DS=selector of a block (size MEMSIZE), still 16-bit default size 50 | 51 | int 3 52 | 53 | ;--- a bug in debugx <= v1.28 was that to accept offsets beyond 64k, the 54 | ;--- default size flag had to be set! 55 | 56 | lar ecx,ebx 57 | shr ecx,8 58 | or ch,40h ;set default to 32-bit 59 | mov ax,9 ;set descriptor flags 60 | int 31h 61 | 62 | ;--- now DS=selector of a descriptor with default size 32-bit 63 | 64 | int 3 65 | 66 | errx: 67 | mov ax, 4C00h ;normal client exit 68 | int 21h 69 | 70 | ;--- now comes the 16bit initialization part 71 | 72 | _TEXT16 segment use16 word public 'CODE' 73 | 74 | start16: 75 | mov ax,ss 76 | mov cx,es 77 | sub ax, cx 78 | mov bx, sp 79 | shr bx, 4 80 | inc bx 81 | add bx, ax 82 | mov ah, 4Ah ;free unused memory 83 | int 21h 84 | 85 | mov ax, 1687h ;DPMI host installed? 86 | int 2Fh 87 | and ax, ax 88 | jnz nohost 89 | push es ;save DPMI entry address 90 | push di 91 | and si, si ;requires host client-specific DOS memory? 92 | jz nomemneeded 93 | mov bx, si 94 | mov ah, 48h ;alloc DOS memory 95 | int 21h 96 | jc nomem 97 | mov es, ax 98 | nomemneeded: 99 | mov ax, DGROUP 100 | mov ds, ax 101 | mov bp, sp 102 | mov ax, 0001 ;start a 32-bit client 103 | call far ptr [bp] ;initial switch to protected-mode 104 | jc initfailed 105 | 106 | ;--- now in protected-mode 107 | 108 | ;--- create a 32bit code selector and jump to 32bit code 109 | 110 | mov cx,1 111 | mov ax,0 112 | int 31h 113 | mov bx,ax 114 | mov cx,_TEXT 115 | mov dx,cx 116 | shl dx,4 117 | shr cx,12 118 | mov ax,7 119 | int 31h ;set base address 120 | mov dx,-1 121 | mov cx,0 122 | mov ax,8 123 | int 31h ;set descriptor limit to 64 kB 124 | mov cx,cs 125 | lar cx,cx 126 | shr cx,8 127 | or ch,40h 128 | mov ax,9 129 | int 31h ;set code descriptors attributes to 32bit 130 | push ebx 131 | push offset start 132 | retd ;jump to 32-bit code 133 | 134 | nohost: 135 | mov dx, offset dErr1 136 | jmp error 137 | nomem: 138 | mov dx, offset dErr2 139 | jmp error 140 | initfailed: 141 | mov dx, offset dErr3 142 | error: 143 | push cs 144 | pop ds 145 | mov ah, 9 146 | int 21h 147 | mov ax, 4C00h 148 | int 21h 149 | 150 | dErr1 db "no DPMI host installed",CR,LF,'$' 151 | dErr2 db "not enough DOS memory for initialisation",CR,LF,'$' 152 | dErr3 db "DPMI initialisation failed",CR,LF,'$' 153 | 154 | _TEXT16 ends 155 | 156 | end start16 157 | -------------------------------------------------------------------------------- /src/TRAPR.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debugger entries for real-mode 3 | ;--- a) program termination 4 | ;--- b) exceptions ( 0, 1, 3, 6, 7, C, D, E ) 5 | ;--- c) sysreq pressed 6 | 7 | ;--- v2.0: code changed so [run_int] is set only if entry is from 8 | ;--- debuggee. If debugger is reentered because of an exception inside 9 | ;--- the debugger, this must not be modified anymore. 10 | 11 | if INT22 12 | ;--- debugger's int 22h (program termination) handler. 13 | ;--- there's no need to preserve registers. 14 | 15 | intr22: 16 | cli 17 | mov cs:[run_int], INT22MSG ;remember interrupt type 18 | mov cs:[lastcmd], offset dmycmd 19 | jmp intrtn_progtrm 20 | 21 | endif 22 | 23 | ;--- Interrupt 0 (divide error) handler. 24 | 25 | intr00: 26 | mov cs:[run_int], EXC00MSG ;remember interrupt type 27 | jmp intrtnr ;jump to register saving routine 28 | 29 | 30 | if CATCHINT01 31 | 32 | if BOOTDBG ;v2.51: MS-DOS 7.1 won't init int 01/03 if sign "JP" is found 33 | db "JP" 34 | endif 35 | ;--- Interrupt 1 (single-step interrupt) handler. 36 | 37 | intr01: 38 | if NOEXC01INDBG 39 | cmp cs:[bInDbg],0 40 | jnz @F 41 | endif 42 | mov cs:[run_int], EXC01MSG 43 | jmp intrtnr 44 | if NOEXC01INDBG 45 | @@: 46 | iret ; just ignore the exception if in debug 47 | endif 48 | 49 | endif 50 | 51 | if CATCHINT06 52 | 53 | intr06: 54 | mov cs:[run_int], EXC06MSG 55 | jmp intrtnr 56 | 57 | endif 58 | 59 | if CATCHINT07 60 | 61 | intr07: 62 | cmp cs:[bInDbg],0 63 | jz @F 64 | mov ax, EXC07MSG 65 | jmp ue_intxx 66 | @@: 67 | mov cs:[run_int], EXC07MSG 68 | jmp intrtnr 69 | 70 | endif 71 | 72 | if CATCHINT0C 73 | 74 | NotOurInt0C: 75 | jmp cs:[oldi0C] 76 | 77 | intr0C: 78 | if MCLOPT 79 | cmp cs:[bMPicB], 20h 80 | jae @F 81 | endif 82 | push ax 83 | mov al, 0Bh ; get ISR mask from PIC 84 | out 20h, al 85 | in al, 20h 86 | test al, 10h ; IRQ4 (int 0Ch) occured? 87 | pop ax 88 | jnz NotOurInt0C 89 | @@: 90 | cmp cs:[bInDbg],0 91 | jz @F 92 | mov ax, EXC0CMSG 93 | jmp ue_intxx 94 | @@: 95 | mov cs:[run_int], EXC0CMSG 96 | jmp intrtnr 97 | 98 | endif 99 | 100 | if CATCHINT0D 101 | 102 | NotOurInt0D: 103 | jmp cs:[oldi0D] 104 | 105 | intr0D: 106 | if MCLOPT 107 | cmp cs:[bMPicB], 20h 108 | jae @F 109 | endif 110 | push ax 111 | mov al, 0Bh ; get ISR mask from PIC 112 | out 20h, al 113 | in al, 20h 114 | test al, 20h ; IRQ5 (int 0Dh) occured? 115 | pop ax 116 | jnz NotOurInt0D 117 | @@: 118 | cmp cs:[bInDbg],0 119 | jz @F 120 | mov ax, EXC0DMSG 121 | jmp ue_intxx 122 | @@: 123 | mov cs:[run_int], EXC0DMSG 124 | jmp intrtnr 125 | 126 | endif 127 | 128 | if CATCHSYSREQ 129 | 130 | @@: 131 | jmp cs:[oldisrq] 132 | intrsrq: 133 | cmp cs:[bInDbg],0 134 | jnz @B 135 | if SYSRQINT eq 15h 136 | cmp ax, 8501h ;sysreq released? 137 | jnz @B 138 | else 139 | pushf 140 | push cs 141 | call @B 142 | push ds 143 | push ax 144 | xor ax, ax 145 | mov ds, ax 146 | pop ax 147 | test byte ptr ds:[418h], 4 ;bit should be set while sysreq is pressed 148 | pop ds 149 | jnz @F 150 | iret 151 | @@: 152 | endif 153 | if ?DPMI 154 | inc cs:[bNoHook2F] ; disable hooking 155 | endif 156 | mov cs:[run_int], SYSRQMSG ;remember interrupt type 157 | jmp intrtnr 158 | 159 | endif 160 | 161 | ;--- Interrupt 3 (breakpoint interrupt) handler. 162 | 163 | intr03: 164 | if SKIPBPINDBG 165 | cmp cs:[bInDbg],0 166 | jz @F 167 | mov ax, EXC03MSG 168 | jmp ue_intxx 169 | @@: 170 | endif 171 | mov cs:[run_int], EXC03MSG ;remember interrupt type 172 | 173 | intrtnr proc 174 | 175 | cli ;just in case 176 | pop cs:[regs.rIP] ;recover things from stack 177 | if ?PM 178 | mov word ptr cs:[regs.rIP+2],0 179 | endif 180 | pop cs:[regs.rCS] 181 | pop cs:[regs.rFL] 182 | intrtn_progtrm:: ;<--- int 22h 183 | mov cs:[regs.rSS],ss;save stack position 184 | sizeprf 185 | mov cs:[regs.rSP],sp 186 | mov sp,cs ; "push cs", "pop ss" without modifying [SP-2] 187 | mov ss,sp 188 | mov sp,offset regs.rSS 189 | 190 | ;--- fall thru to intrtn 191 | 192 | intrtnr endp 193 | -------------------------------------------------------------------------------- /src/INSTR.KEY: -------------------------------------------------------------------------------- 1 | # This is the file "instr.key", which says what the operand-list keys 2 | # mean. 3 | 4 | # Comments are as described in "instr.set". 5 | # Additionally, a semi-colon allows comments in data lines. 6 | 7 | # Keys may be one or two characters. 8 | 9 | # v1.09: - for D and E: OP_16 changed to OP_1632. 10 | # - for S8: OP_IMM8 changed to OP_IMMS8. 11 | # - key L isn't used anymore (was used for 32bit LOOPx). 12 | # v1.18: - keys rearranged, they are now always 2 hex digits. 13 | # - ';' comments added 14 | 15 | 01 OP_ALL+OP_AX, OP_ALL+OP_IMM ;add,adc,and,or,sub, ... 16 | 02 OP_ALL+OP_RM, OP_ALL+OP_IMM ;add,adc,and,or,mov,sub, ... 17 | 03 OP_1632+OP_RM, OP_IMMS8 ;add,adc,and,or,sub, ... 18 | 04 OP_ALL+OP_RM, OP_ALL+OP_R ;add,adc,and,or,mov,sub, ... 19 | 05 OP_ALL+OP_R, OP_ALL+OP_RM ;add,adc,and,or,mov,sub, ... 20 | 06 OP_16+OP_RM, OP_16+OP_R ;arpl 21 | 07 OP_1632+OP_R, OP_1632+OP_M ;bound, LxS 22 | 08 OP_1632+OP_R, OP_1632+OP_RM ;cmovxx, bsf, bsr, imul, lar, lsl 23 | 09 OP_32+OP_R_ADD ;bswap 24 | 0A OP_1632+OP_RM, OP_1632+OP_R ;bt, btr, bts, btc 25 | 0B OP_1632+OP_RM, OP_IMM8 ;bt, btr, bts, btc 26 | 0C OP_REL1632 ;call/jmp near, jxx 27 | 0D OP_FARIMM ;call/jmp seg:ofs 28 | 0E OP_FARMEM ;call/jmp far [mem] 29 | 0F OP_M64 ;cmpxchg8b, fild, fistp 30 | 10 OP_ALL+OP_RM ;dec, inc, imul, ... 31 | 11 OP_1632+OP_R_ADD ;dec, inc, pop, push 32 | 12 OP_16+OP_IMM, OP_IMM8 ;enter 33 | 13 OP_MFLOAT ;fld, fst, ... 34 | 14 OP_MDOUBLE ;fld, fst, ... 35 | 15 OP_ST, OP_STI ;fdiv, fmul, fcmovxx,... 36 | 16 OP_STI, OP_ST ;fadd, fdiv, ... 37 | 17 OP_1CHK, OP_STI, OP_ST ;fxxxp 38 | 18 OP_32+OP_M ;fixxx 39 | 19 OP_16+OP_M ;fixxx 40 | 1A OP_M80 ;fbld, fbstp 41 | 1B OP_STI ;fld, fst, ... 42 | 1C OP_1CHK, OP_STI ;f[u]comx 43 | 1D OP_M80 ;fld, fstp 44 | 1E OP_MXX ;[l|s][g|i]dt, fsave, frstor, fldenv 45 | 1F OP_16+OP_AX ;fstsw 46 | 20 OP_1632+OP_R, OP_1632+OP_RM, OP_IMMS8 ;imul 47 | 21 OP_1632+OP_R_MOD, OP_1632+OP_R, OP_IMMS8 ;imul 48 | 22 OP_1632+OP_R, OP_1632+OP_RM, OP_1632+OP_IMM ;imul 49 | 23 OP_1632+OP_R_MOD, OP_1632+OP_R, OP_1632+OP_IMM ;imul 50 | 24 OP_ALL+OP_AX, OP_IMM8 ;in al|ax|eax, imm 51 | 25 OP_ALL+OP_AX, OP_DX ;in al|ax|eax, dx 52 | 26 OP_3 ;INT 3 53 | 27 OP_IMM8 ;INT xx, AAD xx, AAM xx 54 | 28 OP_REL8 ;jxx, loopxx, jmp short 55 | 29 OP_1632+OP_RM ;call|jmp|push [mem] 56 | 2A OP_16+OP_RM ;ltr, lldt, lmsw, verr, verw, str 57 | 2B OP_1632+OP_RM, OP_SEGREG ;mov |[mem], 58 | 2C OP_SEGREG, OP_1632+OP_RM ;mov ,|[mem] 59 | 2D OP_ALL+OP_AX, OP_ALL+OP_MOFFS ;mov al|ax|eax, [mem] 60 | 2E OP_ALL+OP_MOFFS, OP_ALL+OP_AX ;mov [mem], al|ax|eax 61 | 2F OP_8+OP_R_ADD, OP_8+OP_IMM ;mov , 62 | 30 OP_1632+OP_R_ADD, OP_1632+OP_IMM ;mov , 63 | 31 OP_1632+OP_R, OP_SHOSIZ, OP_8+OP_RM ;movzx, movsx 64 | 32 OP_1632+OP_R, OP_SHOSIZ, OP_16+OP_RM ;movzx, movsx 65 | 33 OP_IMM8, OP_ALL+OP_AX ;out imm, al|ax|eax 66 | 34 OP_DX, OP_ALL+OP_AX ;out dx,al|ax|eax 67 | 35 OP_1632+OP_M ;pop [mem] 68 | 36 OP_1632+OP_IMM ;push 69 | 37 OP_SHOSIZ, OP_IMMS8 ;push byte ptr 70 | 38 OP_ALL+OP_RM, OP_1 ;shl, shr, rol, ror, ... 71 | 39 OP_ALL+OP_RM, OP_CL ;shl, shr, rol, ror, ... 72 | 3A OP_ALL+OP_RM, OP_IMM8 ;shl, shr, rol, ror, ... 73 | 3B OP_16+OP_IMM ;ret x, retf x 74 | 3C OP_8+OP_RM ;setxx 75 | 3D OP_1632+OP_RM, OP_1632+OP_R, OP_IMM8 ;shld, shrd 76 | 3E OP_1632+OP_RM, OP_1632+OP_R, OP_CL ;shld, shrd 77 | 3F OP_1632+OP_AX, OP_1632+OP_R_ADD ;xchg 78 | 40 OP_1632+OP_R_ADD, OP_1632+OP_AX ;xchg 79 | # The next six must be in machine order. 80 | 41 OP_ES 81 | 42 OP_CS 82 | 43 OP_SS 83 | 44 OP_DS 84 | 45 OP_FS 85 | 46 OP_GS 86 | 47 OP_32+OP_R_MOD, OP_CR ;mov , CRx 87 | 48 OP_CR, OP_32+OP_R_MOD ;mov CRx, 88 | 49 OP_32+OP_R_MOD, OP_DR ;mov ,DRx 89 | 4A OP_DR, OP_32+OP_R_MOD ;mov DRx, 90 | 4B OP_32+OP_R_MOD, OP_TR ;mov ,TRx 91 | 4C OP_TR, OP_32+OP_R_MOD ;mov TRx, 92 | 4D OP_MMX, OP_32+OP_RM ;movd 93 | 4E OP_32+OP_RM, OP_MMX ;movd 94 | 4F OP_MMX, OP_64+OP_RM ;movq 95 | 50 OP_64+OP_RM, OP_MMX ;movq 96 | -------------------------------------------------------------------------------- /LDebugB/LDEBUGB.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- load DebugB into FASTBOOT JLM 3 | ;--- assemble: JWasm -mz LDebugB.asm 4 | 5 | .286 6 | .model tiny 7 | .dosseg 8 | .stack 2048 9 | option casemap:none 10 | .386 11 | 12 | CStr macro text:vararg 13 | local sym 14 | .const 15 | sym db text,0 16 | .code 17 | exitm 18 | endm 19 | 20 | DStr macro text:vararg 21 | local sym 22 | .const 23 | sym db text,'$' 24 | .code 25 | exitm 26 | endm 27 | 28 | .const 29 | helptxt label byte 30 | db "LDebugB supplies file DEBUGB.BIN to FASTBOOT JLM.",13,10 31 | db "Required:",13,10 32 | db " - Jemm v5.86+",13,10 33 | db " - Jemm loaded with option FASTBOOT",13,10 34 | db " - FASTBOOT.DLL be loaded",13,10 35 | db '$' 36 | 37 | .code 38 | 39 | main proc 40 | 41 | local dwFB:dword 42 | 43 | cld 44 | mov si,81h 45 | nextchr: 46 | lodsb es:[si] 47 | cmp al,13 48 | jz cmdl_done 49 | cmp al,20h 50 | jbe nextchr 51 | mov dx,offset helptxt 52 | mov ah,9 53 | int 21h 54 | ret 55 | cmdl_done: 56 | mov bx,4435h ;FASTBOOT/REBOOT device ID 57 | mov ax,1684h ;get API entry point 58 | int 2Fh 59 | cmp al,0 60 | jnz not_installed 61 | mov word ptr dwFB+0,di 62 | mov word ptr dwFB+2,es 63 | mov ah,0 ;get version 64 | call dwFB 65 | jc not_installed 66 | test ah,1 ;FASTBOOT variant? 67 | jz not_installed 68 | 69 | call loaddebugb ;load DEBUGB.BIN into memory 70 | jc no_debugb 71 | 72 | ;--- FASTBOOT API AH=3: DS:SI=start debugb, ECX=size debugb in bytes 73 | 74 | push ds 75 | mov ds,di 76 | movzx ecx, si 77 | xor si,si 78 | mov ah,3 79 | call dwFB 80 | pop ds 81 | jc no_debugb2 82 | mov dx,DStr("DEBUGB.BIN loaded") 83 | mov ah,9 84 | int 21h 85 | call lfout 86 | ret 87 | 88 | no_debugb2: 89 | mov dx,DStr("DEBUGB.BIN invalid",13,10) 90 | mov ah,9 91 | int 21h 92 | no_debugb: 93 | mov dx,DStr("couldn't load DEBUGB.BIN") 94 | mov ah,9 95 | int 21h 96 | call lfout 97 | ret 98 | not_installed: 99 | mov dx,DStr("FASTBOOT not installed") 100 | mov ah,9 101 | int 21h 102 | call lfout 103 | ret 104 | main endp 105 | 106 | lfout proc 107 | mov dx,DStr(13,10) 108 | mov ah,9 109 | int 21h 110 | ret 111 | lfout endp 112 | 113 | ;--- get file size in EAX 114 | 115 | getfilesize proc 116 | mov ax,4202h 117 | xor cx,cx 118 | xor dx,dx 119 | int 21h 120 | jc exit 121 | push dx 122 | push ax 123 | xor cx,cx 124 | xor dx,cx 125 | mov ax,4200h 126 | int 21h 127 | pop eax 128 | exit: 129 | ret 130 | getfilesize endp 131 | 132 | ;--- load file DEBUGB.BIN into memory. 133 | ;--- out: DI=segment where debugb.bin has been loaded, 134 | ;--- SI=size in bytes; 135 | ;--- C on errors. 136 | ;--- file debugb.bin must be in current directory. 137 | 138 | loaddebugb proc 139 | mov dx,CStr("DEBUGB.BIN") 140 | mov ax,3D00h 141 | int 21h 142 | jc open_error 143 | mov bx,ax 144 | call getfilesize 145 | jc open_error 146 | cmp eax,10000h 147 | jnc file_too_big 148 | mov di,bx 149 | mov si,ax 150 | mov ebx,eax 151 | add ebx,16-1 152 | shr ebx,4 153 | mov ah,48h 154 | int 21h 155 | jc out_of_memory 156 | mov bx,di 157 | mov di,ax 158 | push ds 159 | mov ds,ax 160 | mov dx,0 161 | mov cx,si 162 | mov ax,3F00h 163 | int 21h 164 | pop ds 165 | jc read_error 166 | cmp ax,cx 167 | jnz read_error 168 | mov ah,3Eh 169 | int 21h 170 | ret 171 | open_error: 172 | mov dx,DStr("DEBUGB.BIN open error") 173 | jmp error 174 | file_too_big: 175 | mov dx,DStr("DEBUGB.BIN too big") 176 | jmp error 177 | out_of_memory: 178 | mov dx,DStr("out_of_memory") 179 | jmp error 180 | read_error: 181 | mov dx,DStr("DEBUGB.BIN read error") 182 | error: 183 | mov ah,9 184 | int 21h 185 | call lfout 186 | stc 187 | ret 188 | loaddebugb endp 189 | 190 | start: 191 | mov ax,cs 192 | mov ds,ax 193 | mov dx,ss 194 | sub dx,ax 195 | shl dx,4 196 | mov ss,ax 197 | add sp,dx 198 | mov bx,sp 199 | shr bx,4 200 | mov cx,es 201 | sub ax,cx 202 | add bx,ax 203 | mov ah,4Ah 204 | int 21h 205 | call main 206 | mov ah,4ch 207 | int 21h 208 | 209 | end start 210 | 211 | -------------------------------------------------------------------------------- /src/TRAPD.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debugger entries for DPMI protected-mode 3 | ;--- exceptions ( 0, 1, 3, 6, 7, C, D, E ) 4 | 5 | ;--- stack frames DPMI exception handlers 16/32-bit 6 | 7 | EXFR16 struc 8 | dw 8 dup (?) ; pusha 9 | wMsg dw ? 10 | dw 2 dup (?) ; far16 return to DPMI 11 | wErrC dw ? 12 | rIP dw ? 13 | rCS dw ? 14 | rFL dw ? 15 | rSP dw ? 16 | rSS dw ? 17 | EXFR16 ends 18 | 19 | EXFR32 struc 20 | dd 8 dup (?) ; pushad 21 | wMsg dw ? 22 | dd 2 dup (?) ; far32 return to DPMI 23 | dwErrC dd ? 24 | rEIP dd ? 25 | rCS dw ? 26 | dw ? 27 | rEFL dd ? 28 | rESP dd ? 29 | rSS dw ? 30 | dw ? 31 | EXFR32 ends 32 | 33 | excxx_16: 34 | pusha 35 | mov bp,sp 36 | push ds 37 | mov ds,cs:[dssel] 38 | mov ax,[bp].EXFR16.rIP 39 | mov bx,[bp].EXFR16.rCS 40 | mov cx,[bp].EXFR16.rFL 41 | mov dx,[bp].EXFR16.rSP 42 | mov si,[bp].EXFR16.rSS 43 | mov di,[bp].EXFR16.wMsg 44 | mov [bp].EXFR16.rCS, cs 45 | mov [bp].EXFR16.rSS, ds 46 | cmp [bInDbg],0 ;did the exception occur inside DEBUG? 47 | jz isdebuggee16 48 | if EXCCSIP 49 | mov si, bx 50 | endif 51 | mov [bp].EXFR16.rIP,offset ue_intx 52 | mov bx, [top_sp] 53 | sub bx, 3*2 54 | mov [bx+0], di 55 | if EXCCSIP 56 | mov [bx+2], si 57 | mov [bx+4], ax 58 | endif 59 | mov [bp].EXFR16.rSP, bx 60 | and byte ptr [bp].EXFR16.rFL+1, not 1 ;reset TF 61 | pop ax 62 | jmp back2dpmi16 63 | isdebuggee16: 64 | mov [bp].EXFR16.rIP, offset intrtn 65 | and byte ptr [bp].EXFR16.rFL+1, not 3 ;reset IF + TF 66 | mov [bp].EXFR16.rSP, offset regs.rSS 67 | mov [regs.rIP],ax 68 | mov word ptr [regs.rIP+2],0 69 | mov [regs.rCS],bx 70 | mov [regs.rFL],cx 71 | mov [regs.rSP],dx 72 | mov [regs.rSS],si 73 | mov [run_intw],di 74 | ; pop ax 75 | ; mov [regs.rDS],ax 76 | ; mov ds,ax 77 | pop ds 78 | back2dpmi16: 79 | popa 80 | add sp, 2 81 | retf 82 | 83 | exc00: 84 | push EXC00MSG 85 | jmp exc_xx 86 | exc01: 87 | push EXC01MSG 88 | jmp exc_xx 89 | exc03: 90 | push EXC03MSG 91 | jmp exc_xx 92 | if CATCHEXC06 93 | exc06: 94 | push EXC06MSG 95 | jmp exc_xx 96 | endif 97 | if CATCHEXC07 98 | exc07: 99 | push EXC07MSG 100 | jmp exc_xx 101 | endif 102 | if CATCHEXC0C 103 | exc0c: 104 | push EXC0CMSG 105 | jmp exc_xx 106 | endif 107 | exc0d: 108 | push EXC0DMSG 109 | jmp exc_xx 110 | exc0e: 111 | push EXC0EMSG 112 | exc_xx: 113 | test cs:[dpmi32],1 114 | jz excxx_16 115 | 116 | .386 117 | 118 | pushad 119 | mov ebp,esp 120 | push ds 121 | mov ds,cs:[dssel] 122 | mov eax,[ebp].EXFR32.rEIP 123 | mov bx, [ebp].EXFR32.rCS 124 | mov ecx,[ebp].EXFR32.rEFL 125 | mov edx,[ebp].EXFR32.rESP 126 | mov si, [ebp].EXFR32.rSS 127 | mov di, [ebp].EXFR32.wMsg 128 | mov [ebp].EXFR32.rCS, cs 129 | mov [ebp].EXFR32.rSS, ds 130 | cmp [bInDbg],0 ;did the exception occur inside DEBUG? 131 | jz isdebuggee32 132 | if EXCCSIP 133 | ;--- it's assumed that an exception in DEBUG is always in 16-bit code, 134 | ;--- but this isn't necessarily true, since the debuggee may have hooked 135 | ;--- exceptions. Since v2.0, this is less probable, because DebugX will 136 | ;--- always restore exception handlers 0D/0E on entry. 137 | mov si, bx 138 | endif 139 | mov [ebp].EXFR32.rEIP,offset ue_intx 140 | movzx ebx,[top_sp] 141 | if EXCCSIP 142 | if EXCCSEIP 143 | sub bx, 2*2+4 144 | else 145 | sub bx, 3*2 146 | endif 147 | else 148 | sub bx, 2 149 | endif 150 | mov [bx+0], di ; msg 151 | if EXCCSIP 152 | mov [bx+2], si ; cs 153 | if EXCCSEIP 154 | mov [bx+4], eax 155 | else 156 | mov [bx+4], ax 157 | endif 158 | endif 159 | mov [ebp].EXFR32.rESP, ebx 160 | and byte ptr [ebp].EXFR32.rEFL+1, not 1 ;reset TF 161 | pop ax 162 | jmp back2dpmi32 163 | isdebuggee32: 164 | @dprintf "excxx: client exception" 165 | mov [ebp].EXFR32.rEIP, offset intrtn 166 | and byte ptr [ebp].EXFR32.rEFL+1, not 3;reset IF + TF 167 | mov [ebp].EXFR32.rESP, offset regs.rSS 168 | mov dword ptr [regs.rIP], eax 169 | mov [regs.rCS],bx 170 | ; mov dword ptr [regs.rFL], ecx ; preferable? 171 | mov [regs.rFL],cx 172 | mov dword ptr [regs.rSP], edx 173 | mov [regs.rSS],si 174 | mov [run_intw],di 175 | ; pop ax 176 | ; mov [regs.rDS],ax 177 | ; mov ds,ax 178 | pop ds 179 | back2dpmi32: 180 | popad 181 | add sp, 2 182 | retd 183 | 184 | -------------------------------------------------------------------------------- /Samples/DPMIBK32.ASM: -------------------------------------------------------------------------------- 1 | 2 | ;--- DPMIBK32.ASM: 32bit DPMI application written in MASM syntax. 3 | ;--- this sample temporarily switches back to real-mode. 4 | ;--- assemble: JWasm -mz dpmibk32.asm 5 | 6 | LF equ 10 7 | CR equ 13 8 | 9 | .386 10 | .model small 11 | 12 | .dosseg ;this ensures that stack segment is last 13 | 14 | .stack 1024 15 | 16 | ;--- DPMI real-mode call structure 17 | 18 | RMCS struct 19 | rEDI dd ? 20 | rESI dd ? 21 | rEBP dd ? 22 | dd ? 23 | rEBX dd ? 24 | rEDX dd ? 25 | rECX dd ? 26 | rEAX dd ? 27 | rFlags dw ? 28 | rES dw ? 29 | rDS dw ? 30 | rFS dw ? 31 | rGS dw ? 32 | rIP dw ? 33 | rCS dw ? 34 | rSP dw ? 35 | rSS dw ? 36 | RMCS ends 37 | 38 | .data 39 | 40 | szWelcome db "welcome in protected-mode",CR,LF,0 41 | szBackinPM db "back in protected-mode",CR,LF,0 42 | 43 | .code 44 | 45 | start: 46 | push eax 47 | mov esi, offset szWelcome 48 | call printstring 49 | pop ebx 50 | 51 | ;--- switch back to real-mode 52 | 53 | sub esp, sizeof RMCS+2 54 | mov ebp,esp 55 | xor eax, eax 56 | mov [ebp].RMCS.rIP, offset backtoreal 57 | mov [ebp].RMCS.rCS, _TEXT16 58 | mov [ebp].RMCS.rFlags, ax 59 | mov [ebp].RMCS.rDS, ax 60 | mov [ebp].RMCS.rES, ax 61 | mov [ebp].RMCS.rFS, ax 62 | mov [ebp].RMCS.rGS, ax 63 | lea eax,[ebp-20h] 64 | mov [ebp].RMCS.rSP, ax 65 | mov [ebp].RMCS.rSS, bx 66 | xor bx,bx 67 | xor cx,cx 68 | mov edi,ebp 69 | push ss 70 | pop es 71 | mov ax,0301h ;temporarily switch to real-mode 72 | int 31h 73 | 74 | mov esi, offset szBackinPM 75 | call printstring 76 | mov ax, 4C00h ;normal client exit 77 | int 21h 78 | 79 | ;--- print a string in protected-mode with simple 80 | ;--- DOS commands not using pointers. 81 | 82 | printstring: 83 | lodsb 84 | and al,al 85 | jz stringdone 86 | mov dl,al 87 | mov ah,2 88 | int 21h 89 | jmp printstring 90 | stringdone: 91 | ret 92 | 93 | ;--- now comes the 16bit initialization part 94 | 95 | _TEXT16 segment use16 word public 'CODE' 96 | 97 | backtoreal: 98 | push cs 99 | pop ds 100 | mov dx,offset dBackinRM 101 | mov ah,9 102 | int 21h 103 | retf ;back to protected-mode 104 | 105 | 106 | start16: 107 | mov ax,ss 108 | mov cx,es 109 | sub ax, cx 110 | mov bx, sp 111 | shr bx, 4 112 | inc bx 113 | add bx, ax 114 | mov ah, 4Ah ;free unused memory 115 | int 21h 116 | 117 | mov ax, 1687h ;DPMI host installed? 118 | int 2Fh 119 | and ax, ax 120 | jnz nohost 121 | push es ;save DPMI entry address 122 | push di 123 | and si, si ;requires host client-specific DOS memory? 124 | jz nomemneeded 125 | mov bx, si 126 | mov ah, 48h ;alloc DOS memory 127 | int 21h 128 | jc nomem 129 | mov es, ax 130 | nomemneeded: 131 | mov ax, DGROUP 132 | mov ds, ax 133 | mov bx, ss 134 | mov bp, sp 135 | mov ax, 0001 ;start a 32-bit client 136 | call far ptr [bp] ;initial switch to protected-mode 137 | jc initfailed 138 | 139 | ;--- now in protected-mode 140 | 141 | ;--- create a 32bit code selector and jump to 32bit code 142 | 143 | push bx ;save stack segment 144 | mov cx,1 145 | mov ax,0 146 | int 31h 147 | mov bx,ax 148 | mov cx,_TEXT 149 | mov dx,cx 150 | shl dx,4 151 | shr cx,12 152 | mov ax,7 153 | int 31h ;set base address 154 | mov dx,-1 155 | mov cx,0 156 | mov ax,8 157 | int 31h ;set descriptor limit to 64 kB 158 | mov cx,cs 159 | lar cx,cx 160 | shr cx,8 161 | or ch,40h 162 | mov ax,9 163 | int 31h ;set code descriptors attributes to 32bit 164 | pop ax ;store stack segment in AX 165 | push ebx 166 | push offset start 167 | retd ;jump to 32-bit code 168 | 169 | nohost: 170 | mov dx, offset dErr1 171 | jmp error 172 | nomem: 173 | mov dx, offset dErr2 174 | jmp error 175 | initfailed: 176 | mov dx, offset dErr3 177 | error: 178 | push cs 179 | pop ds 180 | mov ah, 9 181 | int 21h 182 | mov ax, 4C00h 183 | int 21h 184 | 185 | dErr1 db "no DPMI host installed",CR,LF,'$' 186 | dErr2 db "not enough DOS memory for initialisation",CR,LF,'$' 187 | dErr3 db "DPMI initialisation failed",CR,LF,'$' 188 | dBackinRM db "switched to real-mode",CR,LF,'$' 189 | 190 | _TEXT16 ends 191 | 192 | end start16 193 | -------------------------------------------------------------------------------- /src/DPRINTFR.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debug printf - all registers preserved, including flags 3 | ;--- DEBUGR variant, compatible with 32-bit stack 4 | 5 | handle_char proc 6 | 7 | cmp al,10 8 | jnz @F 9 | mov al,13 10 | call @F 11 | mov al,10 12 | @@: 13 | push bx 14 | xor bx,bx 15 | mov ah,0Eh 16 | call cs:[int10vec] 17 | pop bx 18 | ret 19 | 20 | handle_char endp 21 | 22 | ;--- ltob(long n, char * s, int base); 23 | ;--- convert long to string 24 | ;--- eax=number 25 | ;--- ss:ebx=buffer 26 | ;--- cx=base 27 | 28 | ltob PROC 29 | 30 | push edi 31 | movzx edi, cx 32 | mov ch,0 33 | cmp di,-10 34 | jne @F 35 | mov di,10 36 | and eax,eax 37 | jns @F 38 | neg eax 39 | mov ch,'-' 40 | @@: 41 | add ebx,10 42 | mov BYTE PTR ss:[ebx],0 43 | dec ebx 44 | @@nextdigit: 45 | xor edx, edx 46 | div edi 47 | add dl,'0' 48 | cmp dl,'9' 49 | jbe @F 50 | add dl,7+20h 51 | @@: 52 | mov ss:[ebx],dl 53 | dec ebx 54 | and eax, eax 55 | jne @@nextdigit 56 | cmp ch,0 57 | je @F 58 | mov ss:[ebx],ch 59 | dec ebx 60 | @@: 61 | inc ebx 62 | mov eax,ebx 63 | pop edi 64 | ret 65 | 66 | ltob ENDP 67 | 68 | ;--- ds unused; ss unknown, may be 16- or 32-bit. 69 | ;--- tiny model ( strings may be addressed with CS ) assumed. 70 | 71 | dprintf PROC 72 | 73 | d_esp equ 74 | d_ret equ 75 | d_fmt equ 76 | d_args equ <[ebp+32+2+4+2+2]> 77 | 78 | d_size equ 79 | d_flag equ 80 | d_longarg equ 81 | d_fill equ 82 | d_szTmp equ <[ebp-18]> 83 | 84 | push esp 85 | pushf 86 | pushad 87 | mov ebp, esp 88 | sub esp, 18 89 | mov ax, ss 90 | lar eax, eax 91 | bt eax, 22 92 | jc @F 93 | movzx ebp, bp 94 | @@: 95 | lea edi, d_args 96 | @@L335: 97 | mov si, d_fmt 98 | nextchar: 99 | lodsb cs:[si] 100 | or al,al 101 | je done 102 | cmp al,'%' 103 | je formatitem 104 | call handle_char 105 | jmp nextchar 106 | done: 107 | sub edi, 2 108 | mov ax, d_ret 109 | mov ss:[edi], ax 110 | mov d_esp, edi 111 | add esp, 18 112 | popad 113 | popf 114 | pop esp 115 | ret 116 | 117 | formatitem: 118 | push @@L335 119 | xor dx,dx 120 | mov d_longarg,dl 121 | mov bl,1 122 | mov cl,' ' 123 | cmp BYTE PTR cs:[si],'-' 124 | jne @F 125 | dec bx 126 | inc si 127 | @@: 128 | mov d_flag, bl 129 | cmp BYTE PTR cs:[si],'0' 130 | jne @F 131 | mov cl,'0' 132 | inc si 133 | @@: 134 | mov d_fill,cl 135 | mov bx,dx 136 | @@: 137 | lodsb cs:[si] 138 | cmp al, '0' 139 | jb numdone 140 | cmp al, '9' 141 | ja numdone 142 | sub al,'0' 143 | cbw 144 | imul cx,bx,10 ;cx = bx * 10 145 | add ax,cx 146 | mov bx,ax 147 | jmp @B 148 | numdone: 149 | dec si 150 | mov d_size, bx 151 | cmp BYTE PTR cs:[si],'l' 152 | jne @F 153 | mov d_longarg,1 154 | inc si 155 | @@: 156 | lodsb cs:[si] 157 | mov d_fmt,si 158 | cmp al,'x' 159 | je handle_x 160 | cmp al,'X' 161 | je handle_x 162 | cmp al,'c' 163 | je handle_c 164 | cmp al,'d' 165 | je handle_d 166 | cmp al,'i' 167 | je handle_i 168 | cmp al,'s' 169 | je handle_s 170 | cmp al,'u' 171 | je handle_u 172 | cmp al,0 173 | jnz @@L359 174 | pop ax 175 | jmp done 176 | handle_c: 177 | mov ax,ss:[edi] 178 | add edi,2 179 | @@L359: 180 | call handle_char 181 | retn 182 | 183 | handle_x: 184 | mov cx,16 185 | jmp @@lprt262 186 | handle_d: 187 | handle_i: 188 | mov cx,-10 189 | jmp @@lprt262 190 | handle_u: 191 | mov cx,10 192 | @@lprt262: 193 | mov ax,ss:[edi] 194 | add edi,2 195 | sub dx,dx 196 | cmp cx,0 ;signed or unsigned? 197 | jge @F 198 | cwd 199 | @@: 200 | cmp d_longarg,0 201 | je @F 202 | mov dx,ss:[edi] 203 | add edi,2 204 | @@: 205 | lea ebx, d_szTmp 206 | 207 | push dx 208 | push ax 209 | pop eax 210 | ; invoke ltob, eax, bx, cx 211 | call ltob 212 | mov esi,eax 213 | .while byte ptr ss:[esi] 214 | lodsb ss:[esi] 215 | call handle_char 216 | .endw 217 | retn 218 | 219 | handle_s: 220 | mov si,ss:[edi] 221 | add edi,2 222 | 223 | output_string: ;display string at ds:si 224 | mov ax,si 225 | mov bx,d_size 226 | .while byte ptr cs:[si] 227 | inc si 228 | .endw 229 | sub si,ax 230 | xchg ax,si 231 | sub bx,ax 232 | .if d_flag == 1 233 | .while sword ptr bx > 0 234 | mov al, d_fill 235 | call handle_char 236 | dec bx 237 | .endw 238 | .endif 239 | 240 | .while byte ptr cs:[si] 241 | lodsb cs:[si] 242 | call handle_char 243 | .endw 244 | 245 | .while sword ptr bx > 0 246 | mov al, d_fill 247 | call handle_char 248 | dec bx 249 | .endw 250 | retn 251 | 252 | dprintf ENDP 253 | 254 | d_esp equ <> 255 | d_ret equ <> 256 | d_fmt equ <> 257 | d_args equ <> 258 | d_size equ <> 259 | d_flag equ <> 260 | d_longarg equ <> 261 | d_fill equ <> 262 | d_szTmp equ <> 263 | 264 | -------------------------------------------------------------------------------- /src/DPRINTF.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debug printf - all registers preserved, including flags 3 | 4 | if CATCHINT41 5 | ;--- .486 makes jwasm avoid LEAVE generation - problem if stack is 32-bit 6 | ;--- and hiword(ebp) != 0. That can happen for @dprintf inside intr41(). 7 | .486 8 | endif 9 | 10 | handle_char proc 11 | 12 | cmp al,10 13 | jnz @F 14 | mov al,13 15 | call @F 16 | mov al,10 17 | @@: 18 | push bx 19 | xor bx,bx 20 | mov ah,0Eh 21 | if RING0 22 | call cs:[int10vec] 23 | else 24 | int 10h 25 | endif 26 | pop bx 27 | ret 28 | 29 | handle_char endp 30 | 31 | ;--- ltob(long n, char * s, int base); 32 | ;--- convert long to string 33 | ;--- eax=number 34 | ;--- bx=buffer - is expected to be onto stack 35 | ;--- cx=base 36 | 37 | ;ltob PROC stdcall uses edi number:dword, outb:word, base:word 38 | ltob PROC 39 | 40 | push edi 41 | push edx 42 | movzx edi, cx 43 | mov ch,0 44 | cmp di,-10 45 | jne @F 46 | mov di,10 47 | and eax,eax 48 | jns @F 49 | neg eax 50 | mov ch,'-' 51 | @@: 52 | add bx,10 53 | mov BYTE PTR ss:[bx],0 54 | dec bx 55 | @@nextdigit: 56 | xor edx, edx 57 | div edi 58 | add dl,'0' 59 | cmp dl,'9' 60 | jbe @F 61 | add dl,7+20h 62 | @@: 63 | mov ss:[bx],dl 64 | dec bx 65 | and eax, eax 66 | jne @@nextdigit 67 | cmp ch,0 68 | je @F 69 | mov ss:[bx],ch 70 | dec bx 71 | @@: 72 | inc bx 73 | mov ax,bx 74 | pop edx 75 | pop edi 76 | ret 77 | 78 | ltob ENDP 79 | 80 | ;--- ss doesn't need to be dgroup 81 | ;--- v2.01: ss may be 32-bit! 82 | 83 | dprintf PROC 84 | 85 | d_sp equ word ptr [bp+16+2] 86 | d_ret equ word ptr [bp+16+2+2] 87 | d_fmt equ word ptr [bp+16+2+2+2] 88 | d_args equ [bp+16+2+2+2+2] 89 | 90 | if 0 91 | local size_:word 92 | local flag:byte 93 | local longarg:byte 94 | local fill:byte 95 | local szTmp[12]:byte 96 | else 97 | d_size equ <[bp-2]> 98 | d_flag equ 99 | d_longarg equ 100 | d_fill equ 101 | d_szTmp equ <[bp-18]> 102 | endif 103 | 104 | push sp 105 | pushf 106 | pusha 107 | mov bp, sp 108 | sub sp, 18 109 | push ds 110 | push cs 111 | pop ds 112 | lea di, d_args 113 | @@L335: 114 | mov si, d_fmt 115 | nextchar: 116 | lodsb [si] 117 | or al,al 118 | je done 119 | cmp al,'%' 120 | je formatitem 121 | call handle_char 122 | jmp nextchar 123 | done: 124 | sub di, 2 125 | mov ax, d_ret 126 | mov ss:[di], ax 127 | mov d_sp, di 128 | pop ds 129 | mov sp, bp 130 | popa 131 | popf 132 | pop sp 133 | ret 134 | 135 | formatitem: 136 | push @@L335 137 | xor dx,dx 138 | mov d_longarg,dl 139 | mov bl,1 140 | mov cl,' ' 141 | cmp BYTE PTR [si],'-' 142 | jne @F 143 | dec bx 144 | inc si 145 | @@: 146 | mov d_flag, bl 147 | cmp BYTE PTR [si],'0' 148 | jne @F 149 | mov cl,'0' 150 | inc si 151 | @@: 152 | mov d_fill,cl 153 | mov bx,dx 154 | 155 | .while byte ptr [si] >= '0' && byte ptr [si] <= '9' 156 | lodsb 157 | sub al,'0' 158 | cbw 159 | imul cx,bx,10 ;cx = bx * 10 160 | add ax,cx 161 | mov bx,ax 162 | .endw 163 | 164 | mov d_size, bx 165 | cmp BYTE PTR [si],'l' 166 | jne @F 167 | mov d_longarg,1 168 | inc si 169 | @@: 170 | lodsb 171 | mov d_fmt,si 172 | cmp al,'x' 173 | je handle_x 174 | cmp al,'X' 175 | je handle_x 176 | cmp al,'c' 177 | je handle_c 178 | cmp al,'d' 179 | je handle_d 180 | cmp al,'i' 181 | je handle_i 182 | cmp al,'s' 183 | je handle_s 184 | cmp al,'u' 185 | je handle_u 186 | cmp al,0 187 | jnz @@L359 188 | pop ax 189 | jmp done 190 | handle_c: 191 | mov ax,ss:[di] 192 | add di,2 193 | @@L359: 194 | call handle_char 195 | retn 196 | 197 | handle_x: 198 | mov cx,16 199 | jmp @@lprt262 200 | handle_d: 201 | handle_i: 202 | mov cx,-10 203 | jmp @@lprt262 204 | handle_u: 205 | mov cx,10 206 | @@lprt262: 207 | mov ax,ss:[di] 208 | add di,2 209 | sub dx,dx 210 | cmp cx,0 ;signed or unsigned? 211 | jge @F 212 | cwd 213 | @@: 214 | cmp d_longarg,0 215 | je @F 216 | mov dx,ss:[di] 217 | add di,2 218 | @@: 219 | lea bx, d_szTmp 220 | 221 | push eax ; hiword eax must be preserved 222 | 223 | push dx 224 | push ax 225 | pop eax 226 | ; invoke ltob, eax, bx, cx 227 | call ltob 228 | mov si,ax 229 | 230 | pop eax 231 | 232 | push ds 233 | push ss 234 | pop ds 235 | call output_string 236 | pop ds 237 | retn 238 | 239 | handle_s: 240 | mov si,ss:[di] 241 | add di,2 242 | 243 | output_string: ;display string at ds:si 244 | mov ax,si 245 | mov bx,d_size 246 | .while byte ptr [si] 247 | inc si 248 | .endw 249 | sub si,ax 250 | xchg ax,si 251 | sub bx,ax 252 | .if d_flag == 1 253 | .while sword ptr bx > 0 254 | mov al, d_fill 255 | call handle_char 256 | dec bx 257 | .endw 258 | .endif 259 | 260 | .while byte ptr [si] 261 | lodsb 262 | call handle_char 263 | .endw 264 | 265 | .while sword ptr bx > 0 266 | mov al, d_fill 267 | call handle_char 268 | dec bx 269 | .endw 270 | retn 271 | 272 | dprintf ENDP 273 | 274 | -------------------------------------------------------------------------------- /src/TRAPPL.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debugger entries for ring0 long-mode 3 | ;--- a) exceptions ( 0, 1, 3, 6, 7, C, D, E ) 4 | ;--- b) sysreq pressed 5 | 6 | ;--- v2.0: code changed so [run_int] is set only if entry is from 7 | ;--- debuggee. If debugger is reentered because of an exception inside 8 | ;--- the debugger, this var must not be modified anymore. 9 | 10 | SKIPINTGPF equ 1 ; ignore GPFs caused by INT xx 11 | 12 | .386 13 | 14 | FAULT64 struct 15 | _errc dd ?,? 16 | _eip dd ?,? 17 | _cs dd ?,? 18 | _efl dd ?,? 19 | _esp dd ?,? 20 | _ss dd ?,? 21 | FAULT64 ends 22 | 23 | EXCFR struct 24 | wMsg dw ? 25 | wOfsOld dw ? 26 | FAULT64 <> 27 | EXCFR ends 28 | 29 | if CHKIOPL 30 | 31 | CIIFR struct 32 | dwESI dd ? 33 | wAX dw ? 34 | wDS dw ? 35 | wRet dw ? 36 | EXCFR <> 37 | CIIFR ends 38 | 39 | ;--- check if at cs:(e)ip is an IOPL-sensitive instruction that 40 | ;--- caused a GPF. 41 | ;--- in: ESP = CIIFR 42 | ;--- out: C if yes 43 | 44 | checkioplinstr proc 45 | push ds 46 | push ax 47 | push esi 48 | mov esi, [esp].CIIFR._eip 49 | mov ds, word ptr [esp].CIIFR._cs 50 | cld 51 | lodsb ds:[esi] 52 | cmp al, 0FAh ;CLI? 53 | jz isiopl 54 | cmp al, 0FBh ;STI? 55 | jz isiopl 56 | if SKIPINTGPF 57 | cmp al, 0CDh ;INT XX? ( causes GPF if gate's DPL=0 ) 58 | jz isiopl 59 | endif 60 | jmp ci1 61 | @@: 62 | lodsb ds:[esi] 63 | ci1: 64 | cmp al, 0F3h ;REP? 65 | jz @B 66 | cmp al, 066h ;size prefix? 67 | jz @B 68 | 69 | ;--- E4/E5/E6/E7? IN AL/AX,XX - OUT XX,AL/AX 70 | ;--- EC/ED/EE/EF? IN AL/AX,DX - OUT DX,AL/AX 71 | ;--- 6C/6D/6E/6F? INSB/INSW - OUTSB/OUTSW 72 | 73 | and al, 0FCh 74 | cmp al, 0E4h 75 | jz isiopl 76 | cmp al, 0ECh 77 | jz isiopl 78 | cmp al, 6Ch 79 | jz isiopl 80 | pop esi 81 | pop ax 82 | pop ds 83 | clc 84 | ret 85 | isiopl: 86 | pop esi 87 | pop ax 88 | pop ds 89 | stc 90 | ret 91 | checkioplinstr endp 92 | 93 | endif 94 | 95 | ;--- store value of cr2 in exc msg 96 | rendercr2: 97 | cld 98 | push es 99 | push di 100 | push eax 101 | mov es, cs:[wDgroup] 102 | mov di, offset exc0Ecr2 103 | mov eax, cr2 104 | call hexdword 105 | pop eax 106 | pop di 107 | pop es 108 | ret 109 | 110 | ;--- exceptions must be handled by 64-bit code. 111 | 112 | .x64 113 | 114 | @DefEnt64 macro intno 115 | pushw offset oldi&intno 116 | if &intno&h ge 8 117 | pushw EXC&intno&MSG or ( intno&h shl 8 ) or 8000h 118 | jmp [jmpv162] 119 | else 120 | pushw EXC&intno&MSG or ( intno shl 8 ) 121 | jmp [jmpv161] 122 | endif 123 | endm 124 | 125 | _TEXT64 segment 126 | 127 | intr00: ; divide error 128 | @DefEnt64 00 129 | intr01: ; single-step interrupt 130 | @DefEnt64 01 131 | if CATCHINT02 132 | intr02: ; NMI 133 | @DefEnt64 02 134 | endif 135 | intr03: ; breakpoint interrupt 136 | @DefEnt64 03 137 | if CATCHINT06 138 | intr06: 139 | @DefEnt64 06 140 | endif 141 | if CATCHINT07 142 | intr07: 143 | @DefEnt64 07 144 | endif 145 | if CATCHINT0C 146 | intr0C: 147 | @DefEnt64 0C 148 | endif 149 | if CATCHINT0D 150 | intr0D: 151 | @DefEnt64 0D 152 | endif 153 | intr0E: 154 | @DefEnt64 0E 155 | 156 | _TEXT64 ends 157 | 158 | .386 159 | 160 | 161 | if CATCHSYSREQ 162 | 163 | if SYSRQINT eq 15h 164 | .err <'SYSRQINT equ 15h' not implemented for RING0> 165 | endif 166 | 167 | exitwithpopds: 168 | pop ds 169 | @@: 170 | jmp cs:[oldisrq] 171 | intrsrq: 172 | cmp cs:[bInDbg],0 173 | jnz @B 174 | ;--- v2.50: changed strategy - instead of reading port 60h and see if 175 | ;--- SysRq was released, we check the BIOS variable only and if set, set 176 | ;--- TF=1, causing a single-step exception once the irq1 routine is done. 177 | push ds 178 | mov ds, cs:[wFlat] 179 | test byte ptr ds:[418h], 4 ; sysreq pressed? 180 | jz exitwithpopds 181 | or byte ptr [esp+2].IRET32._efl+1, 1 ; set TF=1 182 | mov ds, cs:[wDgroup] 183 | or [bFlagsPM], 2 ; tell debugger that single-step is caused by SysReq 184 | jmp exitwithpopds 185 | endif 186 | 187 | ;--- exceptions with error code 188 | 189 | intrtnp2: 190 | if MCLOPT 191 | cmp cs:[bMPicB], 20h 192 | jae intrtnp 193 | endif 194 | 195 | push ax 196 | if 1 197 | ;--- before checking the PIC, we check the status of EXCFR._cs 198 | ;--- Since IRQs don't push error codes, this would be the 199 | ;--- saved flags then. if IF and bit 1 aren't 1 (202h), it can't be 200 | ;--- an IRQ. 201 | mov ax, word ptr [esp+2].EXCFR._cs 202 | and ax, 202h 203 | cmp ax, 202h 204 | clc 205 | jnz @F 206 | endif 207 | push cx 208 | mov al, 0Bh ; get ISR mask from PIC 209 | mov cl, byte ptr [esp+4].EXCFR.wMsg+1 210 | out 20h, al 211 | and cx, 7 212 | in al, 20h 213 | bt ax, cx 214 | pop cx 215 | @@: 216 | pop ax 217 | jnc intrtnp 218 | and byte ptr [esp].EXCFR.wMsg+1, 7Fh ; no error code on stack 219 | nostop: 220 | push bx 221 | mov bx,[esp+2].EXCFR.wOfsOld 222 | push ds 223 | mov ds, cs:[wDgroup] 224 | push dword ptr [bx] 225 | pop dword ptr [jmpv64] 226 | pop ds 227 | pop bx 228 | test byte ptr [esp].EXCFR.wMsg+1, 80h ; error code real or faked? 229 | lea esp, [esp+2+2] ; skip msg + oldvec addr 230 | jnz @F 231 | add esp, 8 232 | @@: 233 | jmp cs:[jmpv64] 234 | 235 | ;--- exceptions without error code 236 | intrtnp1: 237 | pushd 0 ; add a fake "error code" to the stack frame 238 | push dword ptr [esp+4] ; ensure that msg + wOfsOld are on top of stack 239 | 240 | ;--- Common interrupt routine. 241 | 242 | intrtnp proc 243 | 244 | cmp cs:[bInDbg],0 245 | jz int_dbgee 246 | pop ax ; get msg 247 | if EXCCSIP 248 | add esp, 2+8; skip wOfsOld + error code 249 | pop ecx 250 | add esp, 4 ; skip high32 of rip 251 | pop dx 252 | endif 253 | ; mov ss, cs:[wDgroup] 254 | ; mov sp, cs:[top_sp] 255 | mov ss, cs:[wFlat] 256 | mov esp, dword ptr cs:[top_sp] 257 | if EXCCSIP 258 | if EXCCSEIP 259 | push ecx ; eip 260 | else 261 | push cx ; ip 262 | endif 263 | push dx ; cs 264 | endif 265 | mov ah, 0 266 | push ax ; msg 267 | cmp al, EXC0EMSG 268 | jnz ue_intx 269 | call rendercr2 270 | jmp ue_intx 271 | 272 | int_dbgee: 273 | ;--- check vector traps (set/reset by VT/VC) 274 | push ax 275 | mov al, byte ptr [esp+2].EXCFR.wMsg+1 276 | and ax, 1Fh 277 | bt cs:[wTrappedExc], ax ; exception trapped? 278 | pop ax 279 | jnc nostop 280 | 281 | if CHKIOPL 282 | ;--- check if GPF caused by running CLI/STI/IN/OUT in IOPL=0 283 | cmp byte ptr [esp].EXCFR.wMsg, EXC0DMSG 284 | jnz @F 285 | test byte ptr [esp].EXCFR._efl+1, 30h ;IOPL==0? 286 | jnz @F 287 | push ax 288 | lar ax, word ptr [esp+2].EXCFR._cs 289 | test ah, 60h ; ring 0? 290 | pop ax 291 | jz @F 292 | call checkioplinstr 293 | jc nostop ; if yes, don't stop in debugger 294 | @@: 295 | endif 296 | 297 | push ds 298 | mov ds, cs:[wDgroup] 299 | pop [regs.rDS] 300 | pop [run_intw] 301 | 302 | add esp, 2 ; skip wOfsOld 303 | 304 | ;--- the rest of the stack contents should be preserved ( for skip cmd ) 305 | 306 | pop [regs.dwErrCode] 307 | add esp, 4 308 | pop dword ptr [regs.rIP] 309 | add esp, 4 310 | pop [regs.rCS] 311 | add esp, 4+2 312 | pop dword ptr [regs.rFL] 313 | add esp, 4 314 | pop dword ptr [regs.rSP] ; pop ss:esp 315 | add esp, 4 316 | pop [regs.rSS] 317 | add esp, 4+2 318 | 319 | mov [regs.r0Esp], esp 320 | mov [regs.r0SS], ss 321 | mov ss, [wDgroup] 322 | mov esp, offset regs.rSS 323 | mov ds, [regs.rDS] 324 | 325 | .8086 326 | 327 | ;--- fall thru to intrtn 328 | 329 | intrtnp endp 330 | 331 | -------------------------------------------------------------------------------- /Test/INITPM.INC: -------------------------------------------------------------------------------- 1 | 2 | pushcontext listing 3 | .nolist 4 | .nocref 5 | 6 | ;--- initialization for simple DPMI apps in MZ format. 7 | ;--- loads hdpmi if no host found. 8 | ;--- switches to protected-mode, then jumps to label start32. 9 | 10 | ?LOADSERVER equ 1 ;try to find HDPMI if no DPMI host has been found 11 | ?TEST386 equ 1 ;1=test for 386 cpu 12 | 13 | _TEXT16 segment use16 word public 'CODE' 14 | 15 | ;--- this is the real mode entry with functions 16 | ;--- 1. check if DPMI is there 17 | ;--- 2. if not, try to load HDPMI32 (in UMBs if available) 18 | ;--- 3. switch to PM as 32bit dpmi client 19 | ;--- 4. set segment registers CS,SS,DS to DGROUP (model tiny), ES=PSP 20 | ;--- 5. jump to label _start32. 21 | 22 | start: 23 | 24 | sizep equ [bp-2] 25 | status1 equ [bp-4] 26 | status2 equ [bp-6] 27 | lpproc equ [bp-10] 28 | 29 | InitPM proc 30 | 31 | if ?TEST386 32 | PUSHF 33 | mov AH,70h 34 | PUSH AX 35 | POPF ; on a 80386 in real-mode, bits 15..12 36 | PUSHF ; should be 7, on a 8086 they are F, 37 | POP AX ; on a 80286 they are 0 38 | POPF 39 | and ah,0F0h 40 | JS @F 41 | JNZ IS386 42 | @@: 43 | mov dx,offset errmsg0 44 | jmp error 45 | IS386: 46 | endif 47 | mov ax,sp 48 | add ax,16-1 49 | shr ax,4 50 | mov bx,ss 51 | add bx,ax 52 | mov ax,es 53 | mov si,bx 54 | sub bx,ax 55 | mov ah,4Ah ;resize memory block to free DOS memory 56 | int 21h 57 | 58 | mov bp,sp 59 | 60 | mov ax,es 61 | add ax,10h ;seg _TEXT (masm doesn't like segment fixups in tiny models) 62 | mov ds,ax 63 | sub si,ax 64 | push si ;store size DGROUP (paragraphs) 65 | 66 | mov ax,5802h ;save status umb 67 | int 21h 68 | xor ah,ah 69 | push ax ;status 1 70 | mov ax,5800h ;save memory alloc strategy 71 | int 21h 72 | xor ah,ah 73 | push ax ;status 2 74 | mov bx,0081h ;first high,then low 75 | mov cx,0001h ;include umbs 76 | call setumbstatus 77 | 78 | mov ax,1687h ;is DPMI existing? 79 | int 2fh 80 | and ax,ax 81 | if ?LOADSERVER 82 | jz @F 83 | call loadserver 84 | mov ax,1687h 85 | int 2fh 86 | and ax,ax 87 | jnz nodpmihost 88 | @@: 89 | else 90 | jnz nodpmihost ;error: no DPMI host 91 | endif 92 | push es 93 | push di ;lpproc 94 | 95 | and si,si 96 | jz nomemneeded 97 | ;alloc req real mode mem 98 | mov ah,48h 99 | mov bx,si 100 | int 21h 101 | jc outofmem 102 | 103 | mov es,ax 104 | nomemneeded: 105 | call restoreumbstatus 106 | mov si, ds 107 | mov ax,0001 ;32 bit application 108 | call dword ptr [lpproc] ;jump to PM 109 | jc initfailed 110 | 111 | ;--- here es=PSP, ds=_TEXT (=DGROUP), cs=TEXT16, ss=stack 112 | ;--- limits are 0FFFFh, except for PSP 113 | ;--- size of DGROUP in paragraphs in sizep 114 | ;--- SI=segment address of DGROUP 115 | 116 | ;--- convert SS to DGROUP (might be > 64kB) 117 | movzx eax,word ptr sizep 118 | shl eax,4 119 | push eax 120 | dec eax 121 | push eax 122 | pop dx 123 | pop cx 124 | mov bx,ds 125 | mov ax,8 ;set limit of DGROUP 126 | int 31h 127 | pop eax 128 | mov bx,ss 129 | push ds 130 | pop ss 131 | mov esp,eax 132 | 133 | 134 | ;--- setup 32-bit CS (size DGROUP) 135 | movzx esi, si 136 | shl esi, 4 137 | push esi 138 | pop dx 139 | pop cx 140 | mov ax,7 ;set base CS 141 | int 31h 142 | lea eax,[esp-1] 143 | push eax 144 | pop dx 145 | pop cx 146 | mov ax,8 ;set limit CS 147 | int 31h 148 | mov cx,cs 149 | lar ecx,ecx 150 | shr ecx,8 151 | or ch,40h 152 | mov ax,9 153 | int 31h 154 | 155 | push ebx 156 | pushd start32 157 | retd 158 | 159 | restoreumbstatus: 160 | mov cx,status1 161 | mov bx,status2 162 | setumbstatus: 163 | push cx 164 | mov ax,5801h ;memory alloc strat restore 165 | int 21h 166 | pop bx 167 | mov ax,5803h ;umb link restore 168 | int 21h 169 | retn 170 | 171 | nodpmihost: 172 | call restoreumbstatus 173 | mov dx,offset errmsg1 174 | jmp error 175 | outofmem: 176 | call restoreumbstatus 177 | initfailed: 178 | nodescriptor: 179 | mov dx,offset errmsg2 180 | error: 181 | push cs 182 | pop ds 183 | mov ah,09 ;display error msg 184 | int 21h 185 | mov ax,4CFFh ;and exit to DOS 186 | int 21h 187 | InitPM endp 188 | 189 | if ?TEST386 190 | errmsg0 db "80386 needed",13,10,'$' 191 | endif 192 | errmsg1 db "no DPMI host found",13,10,'$' 193 | errmsg2 db "DPMI initialization failed",13,10,'$' 194 | 195 | if ?LOADSERVER 196 | 197 | ;--- there are 2 versions. the standard one searches 198 | ;--- the PATH variable in environment and scans all 199 | ;--- directories for HDPMI32.EXE. 200 | ;--- the other one just includes HDPMI32.INC 201 | 202 | _SFLAGS_ = 20h ;open with "deny write" 203 | 204 | ; .model small, stdcall 205 | 206 | EXECRM struct 207 | environ dw ? 208 | cmdline dd ? 209 | fcb1 dd ? 210 | fcb2 dd ? 211 | res1 dd ? 212 | res2 dd ? 213 | EXECRM ends 214 | 215 | ;*** this is a real mode proc! *** 216 | 217 | loadserver proc stdcall uses ds es si di 218 | 219 | local psp:word 220 | local env:word 221 | local parmblock:EXECRM 222 | local szCmdLine[2]:byte 223 | local pgmname[80]:byte 224 | 225 | mov ah,51h 226 | int 21h 227 | mov es,bx 228 | assume es:_TEXT16 229 | mov ax,es:[002Ch] 230 | mov psp,bx 231 | mov env,ax 232 | CALL searchpath ;search PATH= variable -> SI, SI=0000 if error 233 | CALL searchpgm ;search HDPMI32 234 | JB error ;---> error exit "not found" 235 | 236 | mov AX,env 237 | mov [parmblock.environ],ax 238 | mov AX,psp 239 | shl eax,16 240 | mov ax,5ch 241 | mov [parmblock.EXECRM.fcb1],eax 242 | mov [parmblock.EXECRM.fcb2],eax 243 | lea ax,szCmdLine 244 | mov word ptr szCmdLine,0 245 | mov word ptr [parmblock.EXECRM.cmdline+0],ax 246 | mov word ptr [parmblock.EXECRM.cmdline+2],ss 247 | 248 | push SS 249 | pop DS ;DS:DX=Path, ES:BX=parameter block 250 | push SS 251 | pop ES 252 | lea DX,pgmname ;path for DPMISV16/32.EXE 253 | lea BX,parmblock 254 | MOV AX,4B00h ;execute server 255 | INT 21h 256 | JB error 257 | xor dx,dx 258 | mov ax,1 259 | ret 260 | error: 261 | xor ax,ax 262 | ret 263 | 264 | ;*** search HDPMI32 in current directory and directories of PATH *** 265 | ;*** Input: SI=address of PATH Variable or NULL (no PATH defined) *** 266 | ;*** : DI=name of 267 | 268 | searchpgm: 269 | push si 270 | mov si,di 271 | lea DI,pgmname 272 | PUSH SS 273 | POP ES 274 | mov dx,di 275 | mov ds,env 276 | nxtc: 277 | lodsb 278 | stosb 279 | cmp al,'\' 280 | jnz @F 281 | mov dx,di 282 | @@: 283 | cmp al,0 284 | jnz nxtc 285 | mov di,dx 286 | pop si 287 | mov bl,0 288 | nextline: ;<---- 289 | PUSH CS 290 | POP DS 291 | PUSH SI 292 | mov si,offset srvname ;name "HDPMI32.EXE" 293 | mov cx,lstr 294 | rep movsb 295 | 296 | push ss 297 | pop ds 298 | lea DX,pgmname 299 | MOV AX,3D00h or _SFLAGS_;try to open "HDPMI32.EXE" 300 | INT 21h 301 | POP SI 302 | JNB found 303 | and bl,bl 304 | jnz @F 305 | mov bl,1 306 | lea di,pgmname ;get current directory 307 | jmp nextline 308 | @@: 309 | AND SI,SI 310 | JZ failed ;PATH isnt defined, so were done 311 | MOV DI,DX 312 | mov ds,env 313 | @@: 314 | lodsb 315 | stosb 316 | CMP AL,';' 317 | JZ @F 318 | CMP AL,00 319 | JNZ @B ;done, nothing found 320 | XOR SI,SI 321 | @@: 322 | DEC DI 323 | CMP Byte Ptr es:[DI-01],'\' 324 | JZ nextline 325 | MOV Byte Ptr es:[DI],'\' 326 | INC DI 327 | JMP nextline 328 | found: 329 | MOV BX,AX 330 | MOV AH,3Eh ;Close File 331 | INT 21h 332 | CLC 333 | RETN 334 | failed: 335 | STC 336 | RETN 337 | 338 | ;*** search PATH in environment *** 339 | ;*** Out: SI-> behind "PATH=" or 0000 *** 340 | ;*** DI-> path of executable in environment 341 | 342 | searchpath: 343 | SUB DI,DI 344 | xor dx,dx 345 | MOV ES,env 346 | PUSH CS 347 | POP DS 348 | nextvar: 349 | MOV SI,offset szPath ;"PATH=" 350 | MOV CX,0005 351 | REPZ CMPSB 352 | JNZ @F 353 | mov dx,di 354 | @@: 355 | mov al,00 356 | mov ch,7Fh 357 | repnz scasb 358 | cmp al,es:[di] 359 | JNZ nextvar 360 | add di,3 ;so DI points to path of executable now 361 | mov si,dx 362 | RETN 363 | 364 | loadserver endp 365 | 366 | szPath db 'PATH=' 367 | srvname db 'HDPMI32.EXE',00 368 | lstr equ $ - srvname 369 | 370 | endif 371 | 372 | _TEXT16 ends 373 | 374 | popcontext listing 375 | -------------------------------------------------------------------------------- /src/TRAPP.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debugger entries for ring0 protected-mode 3 | ;--- a) exceptions ( 0, 1, 2, 3, 6, 7, C, D, E ) 4 | ;--- b) sysreq pressed 5 | 6 | ;--- v2.0: code changed so [run_int] is set only if entry is from 7 | ;--- debuggee. If debugger is reentered because of an exception inside 8 | ;--- the debugger, this var must not be modified anymore. 9 | 10 | SKIPINTGPF equ 1 ; ignore GPFs caused by INT xx 11 | 12 | ;--- stack size problem: if "SAFESS equ 0" it's assumed that ring0 stack 13 | ;--- is 32-bit - which may not be true. if ring0 ss is 16-bit, but 14 | ;--- ring3 ss is 32-bit, hiword esp may be != 0 and the debugger will crash. 15 | 16 | SAFESS equ 1 17 | 18 | .386 19 | 20 | FAULT32 struct 21 | _errc dd ? 22 | _eip dd ? 23 | _cs dd ? 24 | _efl dd ? 25 | FAULT32 ends 26 | 27 | EXCFR struct 28 | _ret dw ? 29 | wMsg dw ? 30 | FAULT32 <> 31 | EXCFR ends 32 | 33 | if CHKIOPL 34 | 35 | CIIFR struct 36 | dwESI dd ? 37 | wAX dw ? 38 | wDS dw ? 39 | wRet dw ? 40 | EXCFR <> 41 | CIIFR ends 42 | 43 | ;--- check if at cs:(e)ip is an IOPL-sensitive instruction that 44 | ;--- caused a GPF. 45 | ;--- in: ESP = CIIFR 46 | ;--- out: C if yes 47 | 48 | checkioplinstr proc 49 | push ds 50 | push ax 51 | push esi 52 | lds esi, fword ptr [esp].CIIFR._eip 53 | cld 54 | lodsb ds:[esi] 55 | cmp al, 0FAh ;CLI? 56 | jz isiopl 57 | cmp al, 0FBh ;STI? 58 | jz isiopl 59 | if SKIPINTGPF 60 | cmp al, 0CDh ;INT XX? ( causes GPF if gate's DPL=0 ) 61 | jz isiopl 62 | endif 63 | jmp ci1 64 | @@: 65 | lodsb ds:[esi] 66 | ci1: 67 | cmp al, 0F3h ;REP? 68 | jz @B 69 | cmp al, 066h ;size prefix? 70 | jz @B 71 | 72 | ;--- E4/E5/E6/E7? IN AL/AX,XX - OUT XX,AL/AX 73 | ;--- EC/ED/EE/EF? IN AL/AX,DX - OUT DX,AL/AX 74 | ;--- 6C/6D/6E/6F? INSB/INSW - OUTSB/OUTSW 75 | 76 | and al, 0FCh 77 | cmp al, 0E4h 78 | jz isiopl 79 | cmp al, 0ECh 80 | jz isiopl 81 | cmp al, 6Ch 82 | jz isiopl 83 | pop esi 84 | pop ax 85 | pop ds 86 | clc 87 | ret 88 | isiopl: 89 | pop esi 90 | pop ax 91 | pop ds 92 | stc 93 | ret 94 | checkioplinstr endp 95 | 96 | endif 97 | 98 | if SAFESS 99 | checkss: 100 | push eax 101 | mov ax, ss 102 | lar eax, eax 103 | bt eax, 22 104 | jc @F 105 | movzx esp, sp 106 | @@: 107 | pop eax 108 | ret 109 | endif 110 | 111 | @checkss macro 112 | if SAFESS 113 | call checkss 114 | endif 115 | endm 116 | 117 | ;--- store value of cr2/cr3 in exc msg 118 | rendercr2: 119 | cld 120 | push es 121 | push di 122 | push eax 123 | mov es, cs:[wDgroup] 124 | mov di, offset exc0Ecr2 125 | mov eax, cr2 126 | call hexdword 127 | pop eax 128 | pop di 129 | pop es 130 | ret 131 | 132 | ;--- entries vectors 0,1,2,3,6,7,c,d,e 133 | 134 | intr00: ; divide error 135 | push EXC00MSG or (0 shl 8) 136 | call intrtnp1 137 | jmp cs:[oldi00] 138 | 139 | intr01: ; single-step interrupt/debug exception 140 | push EXC01MSG or (1 shl 8) 141 | call intrtnp1 142 | jmp cs:[oldi01] 143 | 144 | if CATCHINT02 145 | intr02: 146 | push EXC02MSG or (2 shl 8) 147 | call intrtnp1 148 | jmp cs:[oldi02] 149 | endif 150 | 151 | intr03: ; breakpoint interrupt 152 | push EXC03MSG or (3 shl 8) 153 | call intrtnp1 154 | jmp cs:[oldi03] 155 | 156 | if CATCHINT06 157 | intr06: 158 | push EXC06MSG or (6 shl 8) 159 | call intrtnp1 160 | jmp cs:[oldi06] 161 | endif 162 | 163 | if CATCHINT07 164 | intr07: 165 | push EXC07MSG or (7 shl 8) 166 | call intrtnp1 167 | jmp cs:[oldi07] 168 | endif 169 | 170 | if CATCHINT0C 171 | intr0C: 172 | push EXC0CMSG or (12 shl 8) or 8000h 173 | call intrtnp2 174 | jmp cs:[oldi0C] 175 | endif 176 | 177 | if CATCHINT0D 178 | intr0D: 179 | push EXC0DMSG or (13 shl 8) or 8000h 180 | call intrtnp2 181 | jmp cs:[oldi0D] 182 | endif 183 | 184 | intr0E: 185 | push EXC0EMSG or (14 shl 8) or 8000h 186 | call intrtnp2 187 | jmp cs:[oldi0E] 188 | 189 | 190 | if CATCHSYSREQ 191 | 192 | if SYSRQINT eq 15h 193 | .err <'SYSRQINT equ 15h' not implemented for RING0> 194 | endif 195 | 196 | exitwithpopds: 197 | pop ds 198 | @@: 199 | jmp cs:[oldisrq] 200 | intrsrq: 201 | cmp cs:[bInDbg],0 202 | jnz @B 203 | ;--- no way to call the real-mode IRQ handler from here. we check the sysreq 204 | ;--- bit and, if set, set TF=1 - will trigger a single-step fault once the 205 | ;--- interrupt routine is done. 206 | push ds 207 | mov ds, cs:[wFlat] 208 | test byte ptr ds:[418h], 4 ; sysreq pressed? 209 | jz exitwithpopds 210 | or byte ptr [esp+2].IRET32._efl+1, 1 ; set TF=1 211 | mov ds, cs:[wDgroup] 212 | or [bFlagsPM], 2 ; tell debugger that single-step is caused by SysReq 213 | jmp exitwithpopds 214 | endif 215 | 216 | 217 | ;--- exceptions with error code 218 | 219 | intrtnp2: 220 | @checkss 221 | if 0 222 | test byte ptr [esp].EXCFR.wMsg+1, 08 ; int 08-0F? 223 | jz intrtnp 224 | endif 225 | if MCLOPT 226 | cmp cs:[bMPicB], 20h 227 | jae intrtnp 228 | endif 229 | 230 | push ax 231 | if 1 232 | ;--- before checking the PIC, we check the status of EXCFR._cs 233 | ;--- Since IRQs don't push error codes, this would be the 234 | ;--- saved flags then. if IF and bit 1 aren't 1 (202h), it can't be 235 | ;--- an IRQ. 236 | mov ax, word ptr [esp+2].EXCFR._cs 237 | and ax, 202h 238 | cmp ax, 202h 239 | clc 240 | jnz @F 241 | endif 242 | push cx 243 | mov al, 0Bh ; get ISR mask from PIC 244 | mov cl, byte ptr [esp+4].EXCFR.wMsg+1 245 | out 20h, al 246 | and cx, 7 247 | in al, 20h 248 | bt ax, cx 249 | pop cx 250 | @@: 251 | pop ax 252 | jnc intrtnp 253 | ret 2 254 | 255 | ;--- exceptions without error code 256 | intrtnp1: 257 | @checkss 258 | push dword ptr [esp] ; add a fake "error code" to the stack frame 259 | 260 | ;--- Common interrupt routine. 261 | 262 | intrtnp proc 263 | 264 | test byte ptr [esp].EXCFR._efl+2, 2 ; VM set? 265 | jz novm86 266 | nostop: 267 | test byte ptr [esp].EXCFR.wMsg+1, 80h ; error code real or faked? 268 | jnz @F 269 | ret 2+4 ; skip msg + faked error code 270 | @@: 271 | ret 2 272 | novm86: 273 | cmp cs:[bInDbg],0 274 | jz int_dbgee 275 | pop ax ; skip _ret 276 | pop ax ; get msg 277 | pop ecx ; skip error code 278 | if EXCCSIP 279 | pop ecx ; eip 280 | pop edx ; cs 281 | endif 282 | mov ss, cs:[wDgroup] 283 | mov sp, cs:[top_sp] 284 | if EXCCSIP 285 | if EXCCSEIP 286 | push ecx ; eip 287 | else 288 | push cx ; ip 289 | endif 290 | push dx ; cs 291 | endif 292 | mov ah, 0 293 | push ax ; msg 294 | cmp al, EXC0EMSG 295 | jnz ue_intx 296 | call rendercr2 297 | jmp ue_intx 298 | 299 | int_dbgee: 300 | 301 | ;--- check vector traps (set/reset by VT/VC) 302 | push ax 303 | lar ax, word ptr [esp+2].EXCFR._cs 304 | test ah, 60h ; ring 0? 305 | mov al, byte ptr [esp+2].EXCFR.wMsg+1 306 | jz @F 307 | add al, 16 308 | @@: 309 | and ax, 1Fh 310 | bt cs:[wTrappedExc], ax ; exception trapped? 311 | pop ax 312 | jnc nostop 313 | 314 | if CHKIOPL 315 | ;--- check if GPF caused by running CLI/STI/IN/OUT in IOPL=0 316 | cmp byte ptr [esp].EXCFR.wMsg, EXC0DMSG 317 | jnz @F 318 | test byte ptr [esp].EXCFR._efl+1, 30h ;IOPL==0? 319 | jnz @F 320 | push ax 321 | lar ax, word ptr [esp+2].EXCFR._cs 322 | test ah, 60h ; ring 0? 323 | pop ax 324 | jz @F 325 | call checkioplinstr 326 | jc nostop ; if yes, don't stop in debugger 327 | @@: 328 | endif 329 | 330 | push ds 331 | mov ds, cs:[wDgroup] 332 | pop [regs.rDS] 333 | add esp, 2 ; skip return addr 334 | pop [run_intw] 335 | 336 | ;--- the rest of the stack contents should be preserved ( for skip cmd ) 337 | 338 | pop [regs.dwErrCode] 339 | pop dword ptr [regs.rIP] 340 | pop [regs.rCS] 341 | add esp, 2 342 | pop dword ptr [regs.rFL] 343 | mov word ptr [regs.dwErrCode+2],ax ; used to store AX temporarily 344 | lar ax, [regs.rCS] 345 | test ah, 60h ; ring 0 exception? 346 | mov ax,word ptr [regs.dwErrCode+2] 347 | jz @F 348 | pop dword ptr [regs.rSP] ; pop ring3 ss:esp 349 | pop [regs.rSS] 350 | add esp, 2 351 | mov [regs.r0Esp], esp 352 | mov [regs.r0SS], ss 353 | jmp intrtn_r0 354 | @@: 355 | mov dword ptr [regs.rSP], esp ; save ring0 stack in regs 356 | mov [regs.r0Esp], esp ; also store here ( for getr0stk() ) 357 | mov [regs.rSS], ss 358 | mov [regs.r0SS], ss 359 | intrtn_r0: 360 | mov ss, [wDgroup] 361 | mov esp, offset regs.rSS 362 | .8086 363 | mov ds, [regs.rDS] 364 | 365 | ;--- fall thru to intrtn 366 | 367 | intrtnp endp 368 | 369 | -------------------------------------------------------------------------------- /src/FPTOSTR.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- defines procedures 3 | ;--- PowerOf10 4 | ;--- FloatToBCD 5 | ;--- FloatToStr 6 | 7 | ; These are bits in the FP status word. 8 | 9 | FP_LESSTHAN equ 01h 10 | FP_EQUALTO equ 40h 11 | 12 | MAXNUM equ 16 13 | 14 | CONST segment 15 | 16 | ;ten dq 10.0 17 | ;ten16 dq 1.0e16 18 | ;rounder dq 5.0e10 19 | 20 | iexp = 1 21 | 22 | ten_1 label tbyte 23 | repeat 15 24 | dt @CatStr(1.0e,%iexp) 25 | iexp = iexp + 1 26 | endm 27 | 28 | ten_16 label tbyte 29 | repeat 15 30 | dt @CatStr(1.0e,%iexp) 31 | iexp = iexp + 16 32 | endm 33 | 34 | ;--- just the first exponent is necessary for 8-byte doubles 35 | 36 | ten_256 label tbyte 37 | repeat 19 38 | dt @CatStr(1.0e,%iexp) 39 | iexp = iexp + 256 40 | endm 41 | 42 | CONST ends 43 | 44 | ;--- called by FloatToStr 45 | ;--- in: ax=exponent 46 | ;--- modifies: bx, cl 47 | 48 | PowerOf10 proc uses si 49 | 50 | push ax 51 | cmp ax, 0 ;.IF (SWORD PTR ax < 0) 52 | jge @F 53 | neg ax 54 | @@: 55 | fld1 56 | mov bl, al 57 | and bl, 0fh ;bits 0-3 58 | je @F 59 | mov si,offset ten_1 60 | call mul10 61 | @@: 62 | mov bl, al 63 | mov cl, 4 64 | shr bl, cl ;bits 4-7 65 | ; and bl, 0fh 66 | je @F 67 | mov si,offset ten_16 68 | call mul10 69 | @@: 70 | mov bl, ah 71 | and bl, 1fh ;bits 8-12 72 | je @F 73 | mov si,offset ten_256 74 | call mul10 75 | @@: 76 | pop ax 77 | cmp ax, 0 ;.IF (SWORD PTR ax < 0) 78 | jge @F 79 | fdivp st(1), st 80 | ret 81 | @@: 82 | fmulp st(1), st 83 | ret 84 | mul10: 85 | dec bl 86 | push ax 87 | mov al,10 ; sizeof TBYTE 88 | mul bl 89 | xchg bx,ax 90 | pop ax 91 | fld tbyte ptr [bx + si] 92 | fmulp st(1), st 93 | retn 94 | 95 | PowerOf10 ENDP 96 | 97 | ; Convert a floating point register to ASCII. For internal use. 98 | ; The result always has exactly 18 digits, with zero padding on the 99 | ; left if required. 100 | ; 101 | ; Entry: ST(0) = a number to convert, 0 <= ST(0) < 1E19. 102 | ; DI = an 18-character buffer. 103 | ; modifies SI,DI,CX,AX 104 | 105 | FloatToBCD PROC 106 | 107 | if FLATSS 108 | sub esp, 12 109 | mov esi, esp 110 | else 111 | sub sp, 12 112 | mov si, sp 113 | endif 114 | 115 | ; The fbstp instruction converts the top of the stack to a 116 | ; packed BCD form in ten bytes, with two digits per byte. The top 117 | ; byte has the sign, which we ignore. 118 | 119 | if FLATSS 120 | fbstp [esp] 121 | else 122 | fbstp [si] 123 | endif 124 | 125 | ; Now we need to unpack the BCD to ASCII. 126 | 127 | if FLATSS 128 | add esi, 8 129 | else 130 | add si, 8 131 | endif 132 | mov cx, 9 133 | @@: 134 | if FLATSS 135 | mov al, ss:[esi] ; xxxx xxxx AAAA BBBB 136 | dec esi 137 | else 138 | mov al, [si] ; xxxx xxxx AAAA BBBB 139 | dec si 140 | endif 141 | if 0 142 | rol ax, 12 ; BBBB xxxx xxxx AAAA 143 | rol ah, 4 ; xxxx BBBB xxxx AAAA 144 | and ax, 0f0fh ; 0000 BBBB 0000 AAAA 145 | else 146 | db 0D4h,10h ; aam 16: 0000 AAAA 0000 BBBB 147 | xchg al,ah ; 0000 BBBB 0000 AAAA 148 | endif 149 | add ax, 3030h 150 | stosw 151 | loop @B 152 | if FLATSS 153 | add esp, 12 154 | else 155 | add sp, 12 156 | endif 157 | ret 158 | 159 | FloatToBCD ENDP 160 | 161 | ; 162 | ; Convert a double precision number to a string. 163 | ; 164 | ; Entry: SI=fpin = 10-byte double to convert 165 | ; DI=pszDbl = buffer to hold converted double 166 | ; 167 | ; Exit: DI = behind converted double 168 | 169 | FloatToStr PROC USES si 170 | 171 | if FLATSS 172 | _DATA segment 173 | iExp dw 0 174 | ;mystat dw 0 175 | ;szTemp db 22 dup (0) 176 | _DATA ends 177 | else 178 | LOCAL iExp: WORD 179 | LOCAL mystat: WORD 180 | ;local szTemp[22]:BYTE 181 | endif 182 | 183 | ;--- Special case zero has been filtered already (fxtract fails for zero). 184 | 185 | ;--- Check for a negative number. 186 | 187 | mov cl,[si+9] 188 | test cl, 80h 189 | jz @F 190 | and byte ptr [si+9], 07fh ; change to positive 191 | mov al,'-' ; store a minus sign 192 | stosb 193 | @@: 194 | 195 | ;--- load our value onto the stack. 196 | 197 | fld tbyte ptr [si] 198 | fld st 199 | mov [si+9], cl ; restore fpin, must be preserved. 200 | 201 | ; Compute the closest power of 10 below the number. We can't get an 202 | ; exact value because of rounding. We could get close by adding in 203 | ; log10(mantissa), but it still wouldn't be exact. Since we'll have to 204 | ; check the result anyway, it's silly to waste cycles worrying about 205 | ; the mantissa. 206 | ; 207 | ; The exponent is basically log2(fpin). Those of you who remember 208 | ; algebra realize that log2(fpin) x log10(2) = log10(fpin), which is 209 | ; what we want. 210 | 211 | fxtract ; ST=> mantissa, exponent, fpin 212 | fstp st ; drop the mantissa 213 | fldlg2 ; push log10(2) 214 | fmulp st(1), st ; ST = log10(fpin), fpin 215 | fistp iExp ; ST = fpin 216 | 217 | ;--- A 10-byte double can carry almost 19 digits, but fbstp only stores the 218 | ;--- guaranteed 18. If you're doing 10-byte doubles, change the '16' to '18'. 219 | 220 | cmp iExp, 18 221 | jnc notbelow18 222 | 223 | fld st ; ST = fpin, fpin 224 | frndint ; ST = int(fpin), fpin 225 | fcomp st(1) ; ST = fpin, status set 226 | if RING0 227 | fstsw ax 228 | else 229 | fstsw mystat 230 | mov ax, mystat 231 | endif 232 | test ah, FP_EQUALTO 233 | jz notequal 234 | 235 | ;--- We have an integer! Lucky day. Go convert it into a temp buffer. 236 | 237 | push di 238 | ; lea di, szTemp 239 | call FloatToBCD 240 | pop di 241 | 242 | mov ax, MAXNUM+1 243 | mov cx, iExp 244 | sub ax, cx 245 | inc cx 246 | ; lea si, szTemp 247 | mov si, di 248 | add si, ax 249 | 250 | ;--- The off-by-one order of magnitude problem below can hit us here. 251 | ;--- We just trim off the possible leading zero. 252 | 253 | cmp byte ptr [si],'0' 254 | jnz @F 255 | inc si 256 | dec cx 257 | @@: 258 | 259 | ;--- Copy the rest of the converted BCD value to our buffer. 260 | 261 | rep movsb 262 | jmp ftsExit 263 | 264 | notequal: 265 | notbelow18: 266 | 267 | ;--- Have fbstp round to 17 places. 268 | 269 | mov ax, MAXNUM 270 | sub ax, iExp ; adjust exponent to 17 271 | call PowerOf10 272 | 273 | ; Either we have exactly 17 digits, or we have exactly 16 digits. We can 274 | ; detect that condition and adjust now. 275 | 276 | fcom qword ptr [ten_16] 277 | ; x0xxxx00 means top of stack > ten16 278 | ; x0xxxx01 means top of stack < ten16 279 | ; x1xxxx00 means top of stack = ten16 280 | if RING0 281 | fstsw ax 282 | else 283 | fstsw mystat 284 | mov ax, mystat 285 | endif 286 | test ah,1 287 | jz @F 288 | fmul qword ptr [ten_1] 289 | dec iExp 290 | @@: 291 | 292 | ;--- Go convert to BCD. 293 | 294 | push di 295 | lea di, [di+8] 296 | call FloatToBCD 297 | pop di 298 | 299 | ; lea si, [szTemp+1] ; point to converted buffer 300 | lea si, [di+8+1] ; point to converted buffer 301 | 302 | ;--- If the exponent is between -15 and 16, we should express this as a number 303 | ;--- without scientific notation. 304 | 305 | mov cx, [iExp] 306 | push cx 307 | add cx,MAXNUM-1 308 | cmp cx,MAXNUM*2-1 309 | pop cx 310 | ja fts6 ;if scientific notation 311 | 312 | ; If the exponent is less than zero, we insert '0.', then -ecx 313 | ; leading zeros, then 16 digits of mantissa. If the exponent is 314 | ; positive, we copy ecx+1 digits, then a decimal point (maybe), then 315 | ; the remaining 16-ecx digits. 316 | 317 | inc cx 318 | cmp cx, 0 319 | jg @F 320 | mov ax,'.0' 321 | stosw 322 | neg cx 323 | mov al, '0' 324 | rep stosb 325 | mov cx, MAXNUM 326 | jmp fts3 327 | @@: 328 | rep movsb 329 | mov al,'.' 330 | stosb 331 | mov cx, MAXNUM 332 | sub cx, [iExp] 333 | fts3: 334 | rep movsb 335 | 336 | ;--- Trim off trailing zeros. 337 | 338 | @@: 339 | cmp byte ptr [di-1],'0' 340 | jnz @F 341 | dec di 342 | jmp @B 343 | @@: 344 | 345 | ;--- If we cleared out all the decimal digits, kill the decimal point, too. 346 | 347 | cmp byte ptr [di-1], '.' 348 | jnz @F 349 | dec di 350 | @@: 351 | 352 | ;--- That's it. 353 | 354 | jmp ftsExit 355 | fts6: 356 | ; Now convert this to a standard, usable format. If needed, a minus 357 | ; sign is already present in the outgoing buffer, and di already points 358 | ; past it. 359 | 360 | movsb ; copy the first digit 361 | mov al,'.' 362 | stosb ; plop in a decimal point 363 | movsw ; copy four more digits 364 | movsw 365 | movsw ; copy two more digits 366 | 367 | if 0 368 | 369 | ; The printf %g specified trims off trailing zeros here. I dislike 370 | ; this, so I've disabled it. Comment out the if 0 and endif if you 371 | ; want this. 372 | 373 | @@: 374 | cmp byte ptr [di-1],'0' 375 | jz @F 376 | dec di 377 | jmp @B 378 | @@: 379 | endif 380 | 381 | ;--- Shove in the exponent. If you support 10-byte reals, remember to 382 | ;--- allow 4 digits for the exponent. 383 | 384 | mov ax,'+e' 385 | mov dx, [iExp] 386 | and dx, dx 387 | jns @F 388 | neg dx 389 | mov ah,'-' 390 | @@: 391 | stosw 392 | 393 | xchg ax,dx 394 | mov si, 10 395 | mov cx,4 396 | @@: 397 | xor dx, dx 398 | div si 399 | push dx 400 | loop @B 401 | mov cl,4 402 | @@: 403 | pop ax 404 | add al,'0' 405 | stosb 406 | loop @B 407 | 408 | ; add di, 4 ; point to terminator 409 | 410 | ftsExit: 411 | ret 412 | 413 | FloatToStr ENDP 414 | 415 | -------------------------------------------------------------------------------- /README.TXT: -------------------------------------------------------------------------------- 1 | 2 | 1. About Debug/X 3 | 4 | Debug/X is a package of debuggers. The most important ones are: 5 | 6 | - Debug: is a clone of the MS-DOS DEBUG command - although, "clone" 7 | isn't the correct name, because it has many features not available in 8 | the original MS DEBUG. For details see below. 9 | 10 | - DebugX: is an extended version of Debug that allows to debug both 11 | real-mode and protected-mode (DPMI) DOS programs. 12 | 13 | - additional variants like DebugXv, DebugXg, DebugB or DebugR that are 14 | useful for special cases. For details see below. 15 | 16 | 17 | 2. Added/Missing Features 18 | 19 | a. Debug extends MS-Debug in the following ways: 20 | 21 | - The assembler and disassembler support all publicly documented 22 | instructions for Intel chips through the Pentium Pro (P6), except for 23 | the MMX instructions (as for DebugX, MMX is partially supported since 24 | v1.18). The assembler and disassembler inform you if any instruction is 25 | inappropriate for the current processor. 26 | 27 | - FPU Opcodes are supported. 28 | 29 | - The current processor (for the purposes of assembler and disassembler 30 | warnings, above) can be declared to be something else via the following 31 | commands: 32 | 33 | m [x] set current processor. 34 | x=0 current processor is 8088. 35 | x=1..6 current processor is 80x86. 80586 is a Pentium and 36 | 80686 is a Pentium Pro. 37 | no argument = print current CPU/FPU types. 38 | mc [2|N] set math coprocessor. 39 | 2 = math coprocessor is a 287 (only valid if current 40 | processor is a 386). 41 | N = math coprocessor is absent 42 | no argument = math coprocessor is present 43 | 44 | - 'r register [value]' accepts 32-bit register names (for cpu 80386+). 45 | 46 | - You can do `r cx 1234' instead of having to put the `1234' on a 47 | separate line. 48 | 49 | - 'rn' displays FPU register status. 50 | Just the raw hex values of the registers are displayed, though. 51 | 52 | - 'rx' switches among 8086 and 80386 register display (for cpu 80386+). 53 | 54 | - When doing `debug < file', debug will not hang if it reaches an end of 55 | file before encountering a `q' command. 56 | 57 | - This debugger saves and restores the program's Control-C and critical 58 | error interrupts, providing for better isolation between the debugger 59 | and the program being debugged. 60 | 61 | - 'tm 0|1' sets trace command mode, 0 = process INTs (default), 62 | 1 = single-step INTs (the MS-DOS Debug compatible mode). 63 | 64 | - 'xr' allows to reallocate an EMS handle and 'xa' allows to allocate 65 | an "empty" EMS handle (with zero pages) - but only if an EMM v4.0 66 | is present. 67 | 68 | - Besides 'i' and 'o' exist the variations 'iw', 'id', 'ow' and 'od' 69 | to read/write a WORD or DWORD value from/to a port [DWORD values 70 | require a 80386+ cpu]. 71 | 72 | - 'h' can handle dword values. 73 | 74 | - register names can be used anywhere where a number is expected as 75 | input. That is, things like "u cs:ip" do work. 76 | 77 | - 'dm' displays the DOS memory control block (MCB) chain and the 78 | current PSP. 79 | 80 | - if DOS has set its InDOS flag, Debug will avoid to use int 21h 81 | internally, which allows to single-step through DOS code. 82 | 83 | - 'd', 't' and 'u' are automatically repeated if a blank line is 84 | entered. 85 | 86 | b. DebugX has the following additional features: 87 | 88 | - besides real-mode applications it can debug both 16-bit and 32-bit 89 | DPMI clients. 90 | [To debug DPMI clients a DPMI host has to be installed. Tested with 91 | cwsdpmi, hdpmi, WinXP NTVDM, 32rtm. In DosEmu and Windows 95/98/ME 92 | DOS boxes it is required to single-step through the initial switch 93 | to protected-mode, else DebugX will loose control of the debuggee.] 94 | 95 | - 'dl': display LDT descriptor(s) (in protected-mode only) 96 | 97 | - 'di': display interrupt vector(s) 98 | 99 | - 'dx': display extended memory (read via Int 15h, ah=87h). Requires a 100 | 80386 cpu. 'dx' is automatically repeated if a blank line is entered. 101 | Be aware that Int 15h, ah=87h most likely will disable "unreal"-mode 102 | if it was enabled. This may be an unwanted side effect during debugging. 103 | 104 | - 'g','p','t': the 80386+ debug registers may be used if breakpoints are 105 | to be set. This allows setting breakpoints in code that is read-only. 106 | The feature may be switched off by cmdline option /s. It's never active 107 | if DebugX runs on NTVDM or DosEmu, since the debug registers aren't 108 | accessible there. 109 | 110 | - 'rn' displays FPU registers in "readable" format. 111 | 112 | - when running in a Windows XP DOS bos, DebugX will try to load and use 113 | DEBXXVDD.DLL. This DLL will allow DebugX to successfully execute its 114 | low-level disk access commands L and W in this OS - if the user has 115 | administrator rights. DEBXXVDD.DLL is public domain, the source can 116 | be found at http://github.com/Baron-von-Riedesel/debxxf. Please 117 | be aware that you can do severe damage to your disk data if you use 118 | those low-level functions without knowing what you are doing. 119 | 120 | - 'rm' displays MMX registers. 121 | 122 | - commandline option /2 may direct DebugX's output to a monochrome video 123 | adapter if one is available. Useful for emulators that support this 124 | feature ( DosBox-x or 86Box, for example ). Needs at least a VGA 125 | compatible card, and there's no guarantee that it works as expected. 126 | 127 | 128 | c. Optionally, one may create special-purpose variants of Debug. 129 | Run file makex.bat to create them; you'll need the JWasm assembler 130 | for a successful run. The many variants may be confusing, basically 131 | there are 3 branches: 132 | 133 | - debugger without protected-mode support ( Debug, DebugB ) 134 | - debugger with DPMI protected-mode support ( DebugX variants ) 135 | - debugger running in protected-mode ring 0 ( DebugR variants ) 136 | 137 | - DebugB.BIN: a version that is supposed to be loaded during the boot 138 | process, before DOS is loaded. Useful to debug DOS itself during its 139 | initialization phase. For details about how this variant can be launched 140 | see "Installing and Initializing DebugB" in DEBUG.TXT. 141 | 142 | - DebugX variants: 143 | 144 | + DebugXd.COM: a version that doesn't hook int 01 and int 03. This 145 | allows to debug this variant with a "normal" version of Debug(X). 146 | 147 | + DebugXe.COM: a version which hooks interrupts 06, 0Ch and 0Dh in 148 | real-mode. This is for - rare - cases when such exceptions may 149 | occur in real-mode applications. 150 | 151 | + DebugXf.COM: a version which hooks interrupt 31h in protected-mode 152 | and then rejects any attempt to modify exception vectors 01, 03, 153 | 0Dh and 0Eh. This allows to debug DOS-extended applications that 154 | modify these vectors. 155 | 156 | + DebugXg.EXE: a version that is in DOS device driver format. This 157 | variant can be used to debug other device drivers. There are a 158 | few peculiarities: 159 | - commands N and Q are rejected; 160 | - commands R and W can't be used to read/write files; 161 | - interrupt 06 (invalid opcode exception) is hooked; 162 | - commands BP/BC to manage permanent breakpoints are activated. 163 | 164 | + DebugXu.COM: a version that uses "unreal" mode to access extended 165 | memory for the DX command. This is useful to debug applications 166 | that set/use "unreal" mode themselves, because DebugXU will not 167 | change the current "unreal" state by its DX command. 168 | 169 | + DebugXv.COM: a variant that has a few nice features activated 170 | compared to the standard DebugX: 171 | - takes care that screen output of debuggee and debugger are strictly 172 | separated; the 'v' command may be used to watch the debuggee screen 173 | while the debugger is active. 174 | - the SysReq key is detected and will activate the debugger. 175 | - the BP/BC commands are active, allowing permanent breakpoints. 176 | DebugXv is intended to help debugging fullscreen text mode programs. 177 | 178 | - DebugR variants. These variants run in ring0 protected-mode. The 179 | binaries need additional software a) to be loaded and b) to handle the 180 | i/o requests. No DOS API is used ( actually, not even the BIOS is used ) 181 | and hence these are not really "DOS debuggers" anymore. 182 | See "DebugR Basics" in DEBUG.TXT for more details. 183 | 184 | + DebugR.BIN: variant for legacy mode, no support for V86 mode. 185 | + DebugRV.BIN: variant for legacy mode with support for V86 mode. 186 | + DebugRL.BIN: variant for long mode. 187 | 188 | d. The following features of MS Debug are not implemented: 189 | 190 | - Loading of .HEX files. 191 | 192 | 193 | 3. How to (re)build the Debug.COM/DebugX.COM Binaries 194 | 195 | MAKE.BAT is intended for rebuilding the debugger binaries. The 196 | recommended tool for this step is to use the JWasm assembler. 197 | Alternatively, one can use MS Masm, but then a 16-bit OMF linker 198 | will be needed as well (Open Watcom's WLink might do the job). Also, 199 | the DebugRL variant cannot be created with Masm, since it contains 200 | a 64-bit segment. 201 | 202 | 203 | 4. Files Overview 204 | 205 | The files in this distribution are: 206 | 207 | debug.com the executable binary. 208 | debugx.com a DPMI aware version of Debug. 209 | debxxvdd.dll a Win32 dll (VDD) loaded if debugx runs in a Windows XP 210 | NTVDM "DOS box". Makes debugx's L and W command work with 211 | sectors on this platform. 212 | readme.txt this file. 213 | history.txt list of changes. 214 | debug.txt a MS-Debug tutorial originally written by Michael Webster, 215 | extended to describe all additional features of Debug(X). 216 | SAMPLES contains samples of 16 and 32-bit DPMI clients in Masm 217 | syntax. 218 | 219 | The following files, which may be distributed separately, are needed if 220 | debug.com or debugx.com is to be rebuilt: 221 | 222 | debug.asm Assembler source code for both debug.com and debugx.com. 223 | Assemble with JWasm or Masm (see Make.bat). 224 | *.inc several assembly include files, two of them (asmtbl.inc 225 | and distbl.inc) generated by tool mktables. 226 | instr.* input data for mktables. 227 | mktables.c C program to compile the internal instruction-set 228 | tables into files asmtbl.inc/distbl.inc. It's supposed to 229 | be translated with Open Watcom's 16bit compiler WCC. 230 | make.bat batch file to (re)create debug.com and debugx.com. 231 | makecm.bat batch file to (re)create mktables.exe with MS C. 232 | makecw.bat batch file to (re)create mktables.exe with OW C. 233 | makex.bat batch file to create special versions of Debugx. 234 | 235 | 236 | 5. Copyright 237 | 238 | This program is copyrighted, but feel free to distribute and use it 239 | as you wish. For full copyright conditions, see the file debug.asm. 240 | 241 | Paul Vojta 242 | vojta@math.berkeley.edu 243 | 244 | -------------------------------------------------------------------------------- /src/INSTR.SET: -------------------------------------------------------------------------------- 1 | # This is "instr.set", the main instruction set description file. 2 | 3 | # The format of this file is as follows. First of all, blank lines 4 | # and lines whose first character is a '#' are comment lines. 5 | 6 | # Otherwise, each line consists of one or more fields, separated by 7 | # spaces (but not tabs). 8 | 9 | # The first field is the opcode field. It looks like the following: 10 | # _^nxxx 11 | # or _^nxxx/xxx 12 | # or _^nxxx#xxx 13 | # or _^nxxx*xxx 14 | # Here: 15 | # _ (if present) signifies that the line applies only to the 16 | # assembler. 17 | # ^n (if present) is ^0 for AAD or AAM, ^1 for DB, ^2 for DW, 18 | # ^3 for DD, ^4 for ORG, and ^5 for 32 bit operand prefix. 19 | # xxx is an op code mnemonic. 20 | # '/' mean that the following opcode is the 32-bit variant of the 21 | # first one, and a 66h prefix will switch. 22 | # '#' mean that the following opcode is the 32-bit variant of the 23 | # first one, and a 67h prefix will switch. 24 | # '*' mean that the preceding opcode occurs with a WAIT instruction; 25 | # the following, without. 26 | 27 | # The remaining fields describe the possible variants of the instruction. 28 | # They have the following formats: 29 | # _Lxx/r.;n 30 | # _Lxx/r*;n 31 | # _Lxx/r&;n 32 | # _DLxx/r:kk;n 33 | # Here: 34 | # _ (if present) means that this variant is to be used only by 35 | # the assember. 36 | # D (if present) means that this variant is to be used only by 37 | # the disassembler. 38 | # L (if present) means that this is a lockable instruction. 39 | # xx are one or two bytes of the instruction field. 40 | # /r (if present) specifies the "r" part in a MOD MEM/REG byte. 41 | # . indicates that the instruction has no operands. 42 | # * indicates that the byte is a prefix (LOCK or REP...). 43 | # & indicates that the byte is a segment prefix. 44 | # :kk gives an index into the file "instr.key". That file gives 45 | # the operand list associated to the key. The key consists of 46 | # two hex digits. 47 | # ;n (if present) indicates the processor on which this 48 | # instruction first appeared. Here n may be 1 through 6. 49 | # 50 | # The order of the variants is important, because the assembler will take 51 | # the first one that fits the input line. 52 | 53 | # References: 54 | # 55 | # Instruction set from the Intel Pentium Family User's Manual, Vol. 3: 56 | # Architecture and Programming Manual. Information on earlier processors 57 | # from various Intel and third party documentation. Information on new 58 | # Pentium Pro instructions from http://x86.metronet.com 59 | # (http://198.215.126.12). 60 | 61 | # History: 62 | # v1.09: - "loop" opcode has no "ecx" operand anymore in 32bit. 63 | # - changed order 1 3 to 3 1 for arith opcodes. 64 | # v1.10: - "loopw", "loopzw" and "loopnzw" variants added. 65 | # v1.18: - "fldenvw", "fldenvd", "fstenvw", "fstenvd" variants added. 66 | # - "fsavew", "fsaved", "frstorw", "frstord" variants added. 67 | # - "movd" and "movq" added. 68 | 69 | aaa 37. 70 | ^0aad d5:27 71 | ^0aam d4:27 72 | aas 3f. 73 | adc L83/2:03 14:01 L80/2:02 L10:04 12:05 74 | add L83/0:03 04:01 L80/0:02 L00:04 02:05 75 | and L83/4:03 24:01 L80/4:02 L20:04 22:05 76 | arpl 63:06;2 77 | bound 62:07;1 78 | bsf 0fbc:08;3 79 | bsr 0fbd:08;3 80 | ^5bswap 0fc8:09;4 81 | bt 0fa3:0A;3 0fba/4:0B;3 82 | btc L0fbb:0A;3 L0fba/7:0B;3 83 | btr L0fb3:0A;3 L0fba/6:0B;3 84 | bts L0fab:0A;3 L0fba/5:0B;3 85 | call e8:0C ff/2:29 ff/3:0E 9a:0D 86 | cbw/cwde 98. 87 | clc f8. 88 | cld fc. 89 | cli fa. 90 | clts 0f06.;2 91 | cmc f5. 92 | cmova 0f47:08;6 93 | cmovae 0f43:08;6 94 | cmovb 0f42:08;6 95 | cmovbe 0f46:08;6 96 | _cmovc 0f42:08;6 97 | _cmove 0f44:08;6 98 | cmovg 0f4f:08;6 99 | cmovge 0f4d:08;6 100 | cmovl 0f4c:08;6 101 | cmovle 0f4e:08;6 102 | _cmovna 0f46:08;6 103 | _cmovnae 0f42:08;6 104 | _cmovnb 0f43:08;6 105 | _cmovnbe 0f47:08;6 106 | _cmovnc 0f43:08;6 107 | _cmovne 0f45:08;6 108 | _cmovng 0f4e:08;6 109 | _cmovnge 0f4c:08;6 110 | _cmovnl 0f4d:08;6 111 | _cmovnle 0f4f:08;6 112 | cmovno 0f41:08;6 113 | _cmovnp 0f4b:08;6 114 | cmovns 0f49:08;6 115 | cmovnz 0f45:08;6 116 | cmovo 0f40:08;6 117 | _cmovp 0f4a:08;6 118 | cmovpe 0f4a:08;6 119 | cmovpo 0f4b:08;6 120 | cmovs 0f48:08;6 121 | cmovz 0f44:08;6 122 | cmp 83/7:03 3c:01 80/7:02 38:04 3a:05 123 | cmpsb a6. 124 | cmpsw/cmpsd a7. 125 | cmpxchg L0fb0:04;4 126 | cmpxchg8b 0fc7/1:0F;5 127 | cpuid 0fa2.;5 128 | cwd/cdq 99. 129 | daa 27. 130 | das 2f. 131 | _^1db 132 | _^3dd 133 | dec 48:11 Lfe/1:10 DLff/1:10 134 | div f6/6:10 135 | _^2dw 136 | emms 0f77.;5 137 | enter c8:12;1 138 | f2xm1 d9f0. 139 | fabs d9e1. 140 | fadd d8/0:13 dc/0:14 d8c0:15 dcc0:16 141 | faddp dec0:17 _dec1. 142 | fiadd da/0:18 de/0:19 143 | fbld df/4:1A 144 | fbstp df/6:1A 145 | fchs d9e0. 146 | fclex*fnclex dbe2. 147 | _fcmova dbd0:15;6 148 | _fcmovae dbc0:15;6 149 | fcmovb dac0:15;6 150 | fcmovbe dad0:15;6 151 | fcmove dac8:15;6 152 | _fcmovna dad0:15;6 153 | _fcmovnae dac0:15;6 154 | fcmovnb dbc0:15;6 155 | fcmovnbe dbd0:15;6 156 | fcmovne dbc8:15;6 157 | fcmovnu dbd8:15;6 158 | _fcmovnz dbc8:15;6 159 | fcmovu dad8:15;6 160 | _fcmovz dac8:15;6 161 | fcom d8/2:13 dc/2:14 d8d0:1C _d8d1. 162 | fcomi dbf0:1C;6 _dbf1.;6 163 | fcomip dff0:1C;6 _dff1.;6 164 | fcomp d8/3:13 dc/3:14 d8d8:1C _d8d9. 165 | fcompp ded9. 166 | fcos d9ff.;3 167 | fdecstp d9f6. 168 | fdisi*fndisi dbe1. 169 | fdiv d8/6:13 dc/6:14 d8f0:15 dcf8:16 170 | fdivp def8:17 _def9. 171 | fidiv da/6:18 de/6:19 172 | fdivr d8/7:13 dc/7:14 d8f8:15 dcf0:16 173 | fdivrp def0:17 _def1. 174 | fidivr da/7:18 de/7:19 175 | feni*fneni dbe0. 176 | ffree ddc0:1B 177 | ficom da/2:18 de/2:19 178 | ficomp da/3:18 de/3:19 179 | fild db/0:18 df/0:19 df/5:0F 180 | fincstp d9f7. 181 | finit*fninit dbe3. 182 | fist db/2:18 df/2:19 183 | fistp db/3:18 df/3:19 df/7:0F 184 | fld d9/0:13 dd/0:14 db/5:1D d9c0:1B 185 | fld1 d9e8. 186 | fldl2t d9e9. 187 | fldl2e d9ea. 188 | fldpi d9eb. 189 | fldlg2 d9ec. 190 | fldln2 d9ed. 191 | fldz d9ee. 192 | fldcw*fnldcw d9/5:19 193 | fldenv d9/4:1E 194 | _fldenvw/fldenvd d9/4:1E 195 | fmul d8/1:13 dc/1:14 d8c8:15 dcc8:16 196 | fmulp dec8:17 _dec9. 197 | fimul da/1:18 de/1:19 198 | fnop d9d0. 199 | fpatan d9f3. 200 | fprem d9f8. 201 | fprem1 d9f5.;3 202 | fptan d9f2. 203 | frndint d9fc. 204 | frstor dd/4:1E 205 | _frstorw/frstord dd/4:1E 206 | fsave*fnsave dd/6:1E 207 | _fsavew/fsaved dd/6:1E 208 | fscale d9fd. 209 | fsetpm*fnsetpm dbe4.;2 210 | fsin d9fe.;3 211 | fsincos d9fb.;3 212 | fsqrt d9fa. 213 | fst d9/2:13 dd/2:14 ddd0:1B 214 | fstp d9/3:13 dd/3:14 db/7:1D ddd8:1B 215 | fstcw*fnstcw d9/7:19 216 | fstenv*fnstenv d9/6:1E 217 | _fstenvw/fstenvd d9/6:1E 218 | fstsw*fnstsw dfe0:1F dd/7:19 219 | fsub d8/4:13 dc/4:14 d8e0:15 dce8:16 220 | fsubp dee8:17 _dee9. 221 | fisub da/4:18 de/4:19 222 | fsubr d8/5:13 dc/5:14 d8e8:15 dce0:16 223 | fsubrp dee0:17 _dee1. 224 | fisubr da/5:18 de/5:19 225 | ftst d9e4. 226 | fucom dde0:1C;3 _dde1.;3 227 | fucomi dbe8:1C;6 _dbe9.;6 228 | fucomip dfe8:1C;6 _dfe9.;6 229 | fucomp dde8:1C;3 _dde9.;3 230 | fucompp dae9.;3 231 | _fwait 9b. 232 | fxam d9e5. 233 | fxch d9c8:1C _d9c9. 234 | fxtract d9f4. 235 | fyl2x d9f1. 236 | fyl2xp1 d9f9. 237 | hlt f4. 238 | idiv f6/7:10 239 | imul f6/5:10 0faf:08;3 6b:20;1 _6b:21;1 69:22;1 _69:23;1 240 | in e4:24 ec:25 241 | inc 40:11 Lfe/0:10 DLff/0:10 242 | insb 6c.;1 243 | insw/insd 6d.;1 244 | int cc:26 cd:27 245 | into ce. 246 | invd 0f08.;4 247 | invlpg 0f01/7:1E;4 248 | iret/iretd cf. 249 | ja 77:28 0f87:0C;3 250 | jae 73:28 0f83:0C;3 251 | jb 72:28 0f82:0C;3 252 | jbe 76:28 0f86:0C;3 253 | _jc 72:28 0f82:0C;3 254 | jcxz#jecxz e3:28 255 | _je 74:28 0f84:0C;3 256 | jg 7f:28 0f8f:0C;3 257 | jge 7d:28 0f8d:0C;3 258 | jl 7c:28 0f8c:0C;3 259 | jle 7e:28 0f8e:0C;3 260 | _jna 76:28 0f86:0C;3 261 | _jnae 72:28 0f82:0C;3 262 | _jnb 73:28 0f83:0C;3 263 | _jnbe 77:28 0f87:0C;3 264 | _jnc 73:28 0f83:0C;3 265 | _jne 75:28 0f85:0C;3 266 | _jng 7e:28 0f8e:0C;3 267 | _jnge 7c:28 0f8c:0C;3 268 | _jnl 7d:28 0f8d:0C;3 269 | _jnle 7f:28 0f8f:0C;3 270 | jno 71:28 0f81:0C;3 271 | _jnp 7b:28 0f8b:0C;3 272 | jns 79:28 0f89:0C;3 273 | jnz 75:28 0f85:0C;3 274 | jo 70:28 0f80:0C;3 275 | _jp 7a:28 0f8a:0C;3 276 | jpe 7a:28 0f8a:0C;3 277 | jpo 7b:28 0f8b:0C;3 278 | js 78:28 0f88:0C;3 279 | jz 74:28 0f84:0C;3 280 | jmp eb:28 e9:0C ff/4:29 ff/5:0E ea:0D 281 | lahf 9f. 282 | lar 0f02:08;2 283 | lds c5:07 284 | lss 0fb2:07;3 285 | les c4:07 286 | lfs 0fb4:07;3 287 | lgs 0fb5:07;3 288 | lea 8d:07 289 | leave c9.;1 290 | lgdt 0f01/2:1E;2 291 | lidt 0f01/3:1E;2 292 | lldt 0f00/2:2A;2 293 | lmsw 0f01/6:2A;2 294 | lock f0* 295 | lodsb ac. 296 | lodsw/lodsd ad. 297 | _loop e2:28 298 | loopw#loopd e2:28 299 | _loopz e1:28 300 | _loope e1:28 301 | _loopew#looped e1:28 302 | loopzw#loopzd e1:28 303 | _loopnz e0:28 304 | _loopne e0:28 305 | _loopnew#loopned e0:28 306 | loopnzw#loopnzd e0:28 307 | lsl 0f03:08;2 308 | ltr 0f00/3:2A;2 309 | # F=mov a,[mem], G=mov [mem],a 4=mov a,r 310 | mov a0:2D a2:2E 88:04 8a:05 8c:2B 8e:2C b0:2F b8:30 c6/0:02 0f20:47;3 0f22:48;3 0f21:49;3 0f23:4A;3 0f24:4B;3 0f26:4C;3 311 | movd 0f6e:4D;5 0f7e:4E;5 312 | movq 0f6f:4F;5 0f7f:50;5 313 | movsb a4. 314 | movsw/movsd a5. 315 | movsx 0fbe:31;3 0fbf:32;3 316 | movzx 0fb6:31;3 0fb7:32;3 317 | mul f6/4:10 318 | neg Lf6/3:10 319 | nop 90. 320 | not Lf6/2:10 321 | or L83/1:03 0c:01 L80/1:02 L08:04 0a:05 322 | _^4org 323 | out e6:33 ee:34 324 | outsb 6e.;1 325 | outsw/outsd 6f.;1 326 | pop 8f/0:35 58:11 1f:44 07:41 17:43 0fa1:45;3 0fa9:46;3 327 | popa/popad 61.;1 328 | popf/popfd 9d. 329 | push 50:11 ff/6:29 6a:37;1 68:36;1 0e:42 16:43 1e:44 06:41 0fa0:45;3 0fa8:46;3 330 | pusha/pushad 60.;1 331 | pushf/pushfd 9c. 332 | rcl d0/2:38 d2/2:39 c0/2:3A;1 333 | rcr d0/3:38 d2/3:39 c0/3:3A;1 334 | rol d0/0:38 d2/0:39 c0/0:3A;1 335 | ror d0/1:38 d2/1:39 c0/1:3A;1 336 | rdmsr 0f32.;5 337 | rdtsc 0f31.;5 338 | rep f3* 339 | repe f3* 340 | repne f2* 341 | ret c3. c2:3B 342 | retf/retfd cb. ca:3B 343 | rsm 0faa.;5 344 | sahf 9e. 345 | _sal d0/4:38 d2/4:39 c0/4:3A;1 346 | sar d0/7:38 d2/7:39 c0/7:3A;1 347 | seg _26:41 _2e:42 _36:43 _3e:44 _64:45 _65:46 348 | es _26& 349 | cs _2e& 350 | ss _36& 351 | ds _3e& 352 | fs _64& 353 | gs _65& 354 | shl d0/4:38 d2/4:39 c0/4:3A;1 355 | shr d0/5:38 d2/5:39 c0/5:3A;1 356 | sbb L83/3:03 1c:01 L80/3:02 L18:04 1a:05 357 | scasb ae. 358 | scasw/scasd af. 359 | seta 0f97:3C;3 360 | setae 0f93:3C;3 361 | setb 0f92:3C;3 362 | setbe 0f96:3C;3 363 | _setc 0f92:3C;3 364 | _sete 0f94:3C;3 365 | setg 0f9f:3C;3 366 | setge 0f9d:3C;3 367 | setl 0f9c:3C;3 368 | setle 0f9e:3C;3 369 | _setna 0f96:3C;3 370 | _setnae 0f92:3C;3 371 | _setnb 0f93:3C;3 372 | _setnbe 0f97:3C;3 373 | _setnc 0f93:3C;3 374 | _setne 0f95:3C;3 375 | _setng 0f9e:3C;3 376 | _setnge 0f9c:3C;3 377 | _setnl 0f9d:3C;3 378 | _setnle 0f9f:3C;3 379 | setno 0f91:3C;3 380 | _setnp 0f9b:3C;3 381 | setns 0f99:3C;3 382 | setnz 0f95:3C;3 383 | seto 0f90:3C;3 384 | _setp 0f9a:3C;3 385 | setpe 0f9a:3C;3 386 | setpo 0f9b:3C;3 387 | sets 0f98:3C;3 388 | setz 0f94:3C;3 389 | sgdt 0f01/0:1E;2 390 | sidt 0f01/1:1E;2 391 | shld 0fa4:3D;3 0fa5:3E;3 392 | shrd 0fac:3D;3 0fad:3E;3 393 | sldt 0f00/0:29;2 394 | smsw 0f01/4:29;2 395 | stc f9. 396 | std fd. 397 | sti fb. 398 | stosb aa. 399 | stosw/stosd ab. 400 | str 0f00/1:2A;2 401 | sub L83/5:03 2c:01 L80/5:02 L28:04 2a:05 402 | test a8:01 f6/0:02 84:04 _84:05 403 | verr 0f00/4:2A;2 404 | verw 0f00/5:2A;2 405 | wait 9b. 406 | wbinvd 0f09.;4 407 | wrmsr 0f30.;5 408 | xadd L0fc0:04;4 409 | xchg 90:3F _90:40 _L86:04 L86:05 410 | xlat _d7. 411 | xlatb d7. 412 | xor L83/6:03 34:01 L80/6:02 L30:04 32:05 413 | -------------------------------------------------------------------------------- /src/TRAPPV.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- debugger entries for ring0 protected-mode, with support for v86 3 | ;--- a) exceptions ( 0, 1, 3, 6, 7, C, D, E ) 4 | ;--- b) sysreq pressed 5 | 6 | ;--- since the code is very low-level and modifies the IDT directly, there's 7 | ;--- a problem with the v86-monitor "breakpoints". They cause a GPF, but should 8 | ;--- be ignored by the debugger. Jemm, for example, uses the HLT opcode (F4) to 9 | ;--- switch out of v86-mode. 10 | 11 | ;--- v2.0: code changed so [run_int] is set only if entry is from 12 | ;--- debuggee. If debugger is reentered because of an exception inside 13 | ;--- the debugger, this var must not be modified anymore. 14 | 15 | SKIPINTGPF equ 1 ; 1=ignore GPFs caused by INT xx 16 | JEMMPLEMU equ 1 ; 1=ignore GPFs for priviledged instructions that Jemm will emulate 17 | 18 | ;--- stack size problem: if "SAFESS equ 0" it's assumed that ring0 stack 19 | ;--- is 32-bit - which may not be true. if ring0 ss is 16-bit, but 20 | ;--- ring3 ss is 32-bit, hiword esp may be != 0 and the debugger will crash. 21 | 22 | SAFESS equ 1 23 | 24 | .386 25 | 26 | IRET32 struct 27 | _eip dd ? 28 | _cs dd ? 29 | _efl dd ? 30 | IRET32 ends 31 | 32 | FAULT32 struct 33 | _errc dd ? 34 | IRET32 <> 35 | FAULT32 ends 36 | 37 | EXCFR struct 38 | _ret dw ? 39 | wMsg dw ? 40 | FAULT32 <> 41 | EXCFR ends 42 | 43 | if CHKIOPL 44 | 45 | CIIFR struct 46 | dwESI dd ? 47 | wAX dw ? 48 | wDS dw ? 49 | wRet dw ? 50 | EXCFR <> 51 | CIIFR ends 52 | 53 | ;--- check if at cs:(e)ip is an IOPL-sensitive instruction that 54 | ;--- caused a GPF. 55 | ;--- in: ESP = CIIFR 56 | ;--- out: C if yes 57 | ;--- for v86 mode, the instructions differ: it's 58 | ;--- CLI, STI, PUSHF, POPF, INT, IRET 59 | ;--- note: this proc is called in v86-mode even if IOPL == 3; 60 | 61 | checkioplinstr proc 62 | push ds 63 | push ax 64 | push esi 65 | cld 66 | test byte ptr [esp].CIIFR._efl+2,2 ;v86-mode? 67 | jz is_pm 68 | movzx esi, word ptr [esp].CIIFR._cs 69 | shl esi, 4 70 | add esi, [esp].CIIFR._eip 71 | mov ds, cs:[wFlat] 72 | 73 | mov al, byte ptr [esp].CIIFR._efl+1 74 | and al, 30h 75 | cmp al, 30h ; V86-mode with IOPL==3? 76 | jz check_io ; then check for IN/OUT only 77 | ;--- check for IOPL sensitive instructions in v86-mode 78 | @@: 79 | lodsb [esi] 80 | cmp al, 66h ;size prefix 81 | jz @B 82 | cmp al, 9Ch ;PUSHF? 83 | jz isiopl 84 | cmp al, 9Dh ;POPF? 85 | jz isiopl 86 | cmp al, 0CDh ;INT? 87 | jz isiopl 88 | cmp al, 0CCh ;INT 3? 89 | jz isiopl 90 | cmp al, 0CFh ;IRET? 91 | jz isiopl 92 | jmp check_clisti 93 | is_pm: 94 | lar ax, word ptr [esp].CIIFR._cs 95 | test ah, 60h ; ring 0 exception? 96 | jz done 97 | mov al, byte ptr [esp].CIIFR._efl+1 98 | and al, 30h 99 | cmp al, 30h ; IOPL==3 in protected-mode? 100 | jz done 101 | @@: 102 | lds esi, fword ptr [esp].CIIFR._eip 103 | lodsb [esi] 104 | check_clisti: 105 | cmp al, 0FAh ;CLI? 106 | jz isiopl 107 | cmp al, 0FBh ;STI? 108 | jz isiopl 109 | if SKIPINTGPF 110 | cmp al, 0CDh ;INT XX? ( causes GPF if gate's DPL=0 ) 111 | jz isiopl 112 | endif 113 | jmp ci1 114 | check_io: 115 | @@: 116 | lodsb [esi] 117 | ci1: 118 | cmp al, 0F3h ;REP? 119 | jz @B 120 | cmp al, 064h ; prefix? 121 | jz @B 122 | cmp al, 065h ; prefix? 123 | jz @B 124 | cmp al, 066h ; prefix? 125 | jz @B 126 | cmp al, 067h ; prefix? 127 | jz @B 128 | cmp al, 026h ; prefix? 129 | jz @B 130 | cmp al, 02Eh ; prefix? 131 | jz @B 132 | cmp al, 036h ; prefix? 133 | jz @B 134 | cmp al, 03Eh ; prefix? 135 | jz @B 136 | 137 | ;--- E4/E5/E6/E7? IN AL/AX,XX - OUT XX,AL/AX 138 | ;--- EC/ED/EE/EF? IN AL/AX,DX - OUT DX,AL/AX 139 | ;--- 6C/6D/6E/6F? INSB/INSW - OUTSB/OUTSW 140 | 141 | and al, 0FCh 142 | cmp al, 0E4h 143 | jz isiopl 144 | cmp al, 0ECh 145 | jz isiopl 146 | cmp al, 6Ch 147 | jz isiopl 148 | done: 149 | pop esi 150 | pop ax 151 | pop ds 152 | clc 153 | ret 154 | isiopl: 155 | pop esi 156 | pop ax 157 | pop ds 158 | stc 159 | ret 160 | checkioplinstr endp 161 | 162 | endif 163 | 164 | ;--- see if an Exc 0D or 06 is caused by a monitor "breakpoint" 165 | ;--- this is called in v86 mode only. 166 | ;--- Jemm uses HLT (F4h) to switch out from v86-mode, 167 | ;--- Win9X uses ARPL (63h). 168 | ;--- Also, for exc 0D, it's checked here if the instruction causing the 169 | ;--- GPF is a mov to/from a special register. Those are 170 | ;--- emulated by Jemm and hence the debugger should route 171 | ;--- these exceptions to the previous handler. 172 | 173 | CVMFR struct 174 | dwESI dd ? 175 | wAX dw ? 176 | wDS dw ? 177 | wRet dw ? 178 | EXCFR <> 179 | CVMFR ends 180 | 181 | checkv86monitorbp proc 182 | push ds 183 | push ax 184 | push esi 185 | movzx esi, word ptr [esp].CVMFR._cs 186 | shl esi, 4 187 | add esi, [esp].CVMFR._eip 188 | mov ds, cs:[wFlat] 189 | cld 190 | lodsb [esi] 191 | cmp al, 0F4h ;HLT should never stop in debugger 192 | jz isv86mon 193 | cmp al, cs:[bV86Bp] ; may be HLT or ARPL 194 | jz isv86mon 195 | cmp byte ptr [esp].CVMFR.wMsg, EXC06MSG 196 | jz done 197 | if JEMMPLEMU 198 | cmp al, 0Fh ;2 byte opcode? (0F 20, 0F 21, 0F 22, 0F 23) 199 | jnz done 200 | lodsb [esi] 201 | cmp al, 20h ;a mov to/from a "special reg" - that's emulated by Jemm 202 | jb done 203 | cmp al, 23h 204 | jbe isv86mon 205 | endif 206 | done: 207 | pop esi 208 | pop ax 209 | pop ds 210 | clc 211 | ret 212 | isv86mon: 213 | pop esi 214 | pop ax 215 | pop ds 216 | stc 217 | ret 218 | checkv86monitorbp endp 219 | 220 | if SAFESS 221 | checkss: 222 | push eax 223 | mov ax, ss 224 | lar eax, eax 225 | bt eax, 22 226 | jc @F 227 | movzx esp, sp 228 | @@: 229 | pop eax 230 | ret 231 | endif 232 | 233 | @checkss macro 234 | if SAFESS 235 | call checkss 236 | endif 237 | endm 238 | 239 | ;--- store value of cr2/cr3 in exc msg 240 | rendercr2: 241 | cld 242 | push es 243 | push di 244 | push eax 245 | mov es, cs:[wDgroup] 246 | mov di, offset exc0Ecr2 247 | mov eax, cr2 248 | call hexdword 249 | pop eax 250 | pop di 251 | pop es 252 | ret 253 | 254 | ;--- entries vectors 0,1,3,6,7,c,d,e 255 | 256 | intr00: ; divide error 257 | push EXC00MSG or (0 shl 8) 258 | call intrtnp1 259 | jmp cs:[oldi00] 260 | 261 | intr01: ; single-step interrupt/debug exception 262 | push EXC01MSG or (1 shl 8) 263 | call intrtnp1 264 | jmp cs:[oldi01] 265 | 266 | if CATCHINT02 267 | intr02: 268 | push EXC02MSG or (2 shl 8) 269 | call intrtnp1 270 | jmp cs:[oldi02] 271 | endif 272 | 273 | intr03: ; breakpoint interrupt 274 | push EXC03MSG or (3 shl 8) 275 | call intrtnp1 276 | jmp cs:[oldi03] 277 | 278 | if CATCHINT06 279 | intr06: 280 | push EXC06MSG or (6 shl 8) 281 | call intrtnp1 282 | jmp cs:[oldi06] 283 | endif 284 | 285 | if CATCHINT07 286 | intr07: 287 | push EXC07MSG or (7 shl 8) 288 | call intrtnp1 289 | jmp cs:[oldi07] 290 | endif 291 | 292 | if CATCHINT0C 293 | intr0C: 294 | push EXC0CMSG or (12 shl 8) or 8000h 295 | call intrtnp2 296 | jmp cs:[oldi0C] 297 | endif 298 | 299 | if CATCHINT0D 300 | intr0D: 301 | push EXC0DMSG or (13 shl 8) or 8000h 302 | call intrtnp2 303 | jmp cs:[oldi0D] 304 | endif 305 | 306 | intr0E: 307 | push EXC0EMSG or (14 shl 8) or 8000h 308 | call intrtnp2 309 | jmp cs:[oldi0E] 310 | 311 | 312 | if CATCHSYSREQ 313 | 314 | if SYSRQINT eq 15h 315 | .err <'SYSRQINT equ 15h' not implemented for RING0> 316 | endif 317 | 318 | exitwithpopds: 319 | pop ds 320 | @@: 321 | jmp cs:[oldisrq] 322 | intrsrq: 323 | cmp cs:[bInDbg],0 324 | jnz @B 325 | ;--- no way to call the real-mode IRQ handler from here. we check the sysreq 326 | ;--- bit and, if set, set TF=1 - will trigger a single-step fault once the 327 | ;--- interrupt routine is done. 328 | push ds 329 | mov ds, cs:[wFlat] 330 | test byte ptr ds:[418h], 4 ; sysreq pressed? 331 | jz exitwithpopds 332 | or byte ptr [esp+2].IRET32._efl+1, 1 ; set TF=1 333 | mov ds, cs:[wDgroup] 334 | or [bFlagsPM], 2 ; tell debugger that single-step is caused by SysReq 335 | bts [wTrappedExc+2], 1 ; is exc 1 trapped? 336 | jc exitwithpopds 337 | or [bFlagsPM], 4 ; if no, mark it in bFlagsPM 338 | jmp exitwithpopds 339 | endif 340 | 341 | ;--- exceptions with error code 342 | 343 | intrtnp2: 344 | @checkss 345 | if 0 346 | test byte ptr [esp].EXCFR.wMsg+1, 08 ; int 08-0F? 347 | jz intrtnp 348 | endif 349 | if MCLOPT 350 | cmp cs:[bMPicB], 20h 351 | jae intrtnp 352 | endif 353 | 354 | push ax 355 | if 1 356 | ;--- before checking the PIC, we check the status of EXCFR._cs 357 | ;--- Since IRQs don't push error codes, this would be the 358 | ;--- saved flags then. if IF and bit 1 aren't 1 (202h), it can't be 359 | ;--- an IRQ. 360 | mov ax, word ptr [esp+2].EXCFR._cs 361 | and ax, 202h 362 | cmp ax, 202h 363 | clc 364 | jnz @F 365 | endif 366 | push cx 367 | mov al, 0Bh ; get ISR mask from PIC 368 | mov cl, byte ptr [esp+4].EXCFR.wMsg+1 369 | out 20h, al 370 | and cx, 7 371 | in al, 20h 372 | bt ax, cx 373 | pop cx 374 | @@: 375 | pop ax 376 | jnc intrtnp 377 | ret 2 378 | 379 | ;--- exceptions without error code 380 | intrtnp1: 381 | @checkss 382 | push dword ptr [esp] ; add a fake "error code" to the stack frame 383 | 384 | ;--- Common interrupt routine. 385 | 386 | intrtnp proc 387 | 388 | jmp novm86 389 | nostop: 390 | test byte ptr [esp].EXCFR.wMsg+1, 80h ; error code real or faked? 391 | jnz @F 392 | ret 2+4 ; skip msg + faked error code 393 | @@: 394 | ret 2 395 | novm86: 396 | cmp cs:[bInDbg],0 397 | jz int_dbgee 398 | 399 | if 1 400 | ;--- if a callout is done to the v86 monitor for I/O, v86-monitor breakpoints will happen 401 | ;--- which the debugger has to ignore in any case. 402 | test byte ptr [esp].EXCFR._efl+2, 2 ; v86mode? 403 | jz v86_check_done 404 | cmp byte ptr [esp].EXCFR.wMsg, EXC0DMSG 405 | jz @F 406 | cmp byte ptr [esp].EXCFR.wMsg, EXC06MSG ;in case ARPL is v86 monitor bp 407 | jnz v86_check_done 408 | @@: 409 | call checkv86monitorbp 410 | jc nostop 411 | cmp byte ptr [esp].EXCFR.wMsg, EXC0DMSG 412 | jnz v86_check_done 413 | call checkioplinstr 414 | jc nostop 415 | v86_check_done: 416 | endif 417 | 418 | pop ax ; skip _ret 419 | pop ax ; get msg 420 | pop ecx ; skip error code 421 | if EXCCSIP 422 | pop ecx ; eip 423 | pop edx ; cs 424 | endif 425 | mov ss, cs:[wDgroup] 426 | movzx esp, cs:[top_sp] 427 | if EXCCSIP 428 | if EXCCSEIP 429 | push ecx ; eip 430 | else 431 | push cx ; ip 432 | endif 433 | push dx ; cs 434 | endif 435 | mov ah, 0 436 | push ax ; msg 437 | cmp al, EXC0EMSG 438 | jnz ue_intx 439 | call rendercr2 440 | jmp ue_intx 441 | 442 | int_dbgee: 443 | 444 | ;--- check vector traps (set/reset by VT/VC) 445 | push ax 446 | mov al, byte ptr [esp+2].EXCFR.wMsg+1 447 | test byte ptr [esp+2].EXCFR._efl+2, 2 ; v86mode? 448 | jz @F 449 | add al, 16 450 | @@: 451 | and ax, 1Fh 452 | bt cs:[wTrappedExc], ax ; exception trapped in ring 0/3? 453 | pop ax 454 | jnc nostop 455 | 456 | ;--- check for v86-monitor bps 457 | 458 | test byte ptr [esp].EXCFR._efl+2, 2 ; v86mode? 459 | jz nobpcheck 460 | cmp byte ptr [esp].EXCFR.wMsg, EXC0DMSG 461 | jz @F 462 | cmp byte ptr [esp].EXCFR.wMsg, EXC06MSG 463 | jnz nobpcheck 464 | @@: 465 | call checkv86monitorbp 466 | jc nostop 467 | nobpcheck: 468 | 469 | if CHKIOPL 470 | ;--- check if GPF caused by an IOPL sensitive instruction in IOPL=0 471 | cmp byte ptr [esp].EXCFR.wMsg, EXC0DMSG 472 | jnz @F 473 | call checkioplinstr 474 | jc nostop ; IOPL sensitive instruction, don't stop! 475 | @@: 476 | endif 477 | 478 | push ds 479 | mov ds, cs:[wDgroup] 480 | pop [regs.rDS] 481 | add esp, 2 ; skip return addr 482 | pop [run_intw] 483 | 484 | ;--- the rest of the stack contents should be preserved ( for skip cmd ) 485 | 486 | pop [regs.dwErrCode] 487 | pop dword ptr [regs.rIP] 488 | pop [regs.rCS] 489 | add esp, 2 490 | pop dword ptr [regs.rFL] 491 | test byte ptr [regs.rFL+2],2 ; v86? 492 | jnz intv86 493 | mov word ptr [regs.dwErrCode+2],ax ; used to store AX temporarily 494 | lar ax, [regs.rCS] 495 | test ah, 60h ; ring 0 exception? 496 | mov ax,word ptr [regs.dwErrCode+2] 497 | jz @F 498 | pop dword ptr [regs.rSP] ; pop ring3 ss:esp 499 | pop [regs.rSS] 500 | add esp, 2 501 | jmp intrtn_r0 502 | intv86: 503 | pop dword ptr [regs.rSP] 504 | pop [regs.rSS] 505 | add esp, 2 506 | pop [regs.rES] 507 | add esp, 2 508 | pop [regs.rDS] 509 | add esp, 2 510 | pop [regs.rFS] 511 | add esp, 2 512 | pop [regs.rGS] 513 | add esp, 2 514 | jmp intrtn_r0 515 | @@: 516 | mov dword ptr [regs.rSP], esp 517 | mov [regs.rSS], ss 518 | intrtn_r0: 519 | mov [regs.r0Esp], esp ; in any case store here ( for "skip" and getr0stk() ) 520 | mov [regs.r0SS], ss 521 | mov ss, [wDgroup] 522 | mov esp, offset regs.rSS 523 | test byte ptr [regs.rFL+2],2 524 | jz @F 525 | sub esp, 4*2 ;skip GS, FS, ES, DS 526 | pushad 527 | jmp intrtn1 528 | @@: 529 | mov ds, [regs.rDS] 530 | .8086 531 | 532 | ;--- fall thru to intrtn 533 | 534 | intrtnp endp 535 | 536 | -------------------------------------------------------------------------------- /src/DISTBL.INC: -------------------------------------------------------------------------------- 1 | 2 | ;--- This file was generated by mktables.exe. 3 | 4 | ;--- compressed table of the opcode types. 5 | ;--- If the item has the format OT(xx), it refers to table 'oplists'. 6 | ;--- Otherwise it's an offset for internal table 'dis_jmp2'. 7 | 8 | OTDATA segment 9 | 10 | optypes label byte 11 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01),OT(40),OT(40) ; 00 - 07 (main opcode part) 12 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01),OT(41), 002h ; 08 - 0f 13 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01),OT(42),OT(42) ; 10 - 17 14 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01),OT(43),OT(43) ; 18 - 1f 15 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01), 00Ah,OT(00) ; 20 - 27 16 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01), 00Ah,OT(00) ; 28 - 2f 17 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01), 00Ah,OT(00) ; 30 - 37 18 | db OT(04),OT(04),OT(05),OT(05),OT(01),OT(01), 00Ah,OT(00) ; 38 - 3f 19 | db OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11) ; 40 - 47 20 | db OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11) ; 48 - 4f 21 | db OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11) ; 50 - 57 22 | db OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11),OT(11) ; 58 - 5f 23 | db OT(00),OT(00),OT(07),OT(06), 00Ah, 00Ah, 00Ah, 00Ah ; 60 - 67 24 | db OT(35),OT(21),OT(36),OT(1F),OT(00),OT(00),OT(00),OT(00) ; 68 - 6f 25 | db OT(27),OT(27),OT(27),OT(27),OT(27),OT(27),OT(27),OT(27) ; 70 - 77 26 | db OT(27),OT(27),OT(27),OT(27),OT(27),OT(27),OT(27),OT(27) ; 78 - 7f 27 | db 004h, 004h, 000h, 004h,OT(04),OT(04),OT(05),OT(05) ; 80 - 87 28 | db OT(04),OT(04),OT(05),OT(05),OT(2A),OT(07),OT(2B), 004h ; 88 - 8f 29 | db OT(00),OT(3E),OT(3E),OT(3E),OT(3E),OT(3E),OT(3E),OT(3E) ; 90 - 97 30 | db OT(00),OT(00),OT(0D),OT(00),OT(00),OT(00),OT(00),OT(00) ; 98 - 9f 31 | db OT(2C),OT(2C),OT(2D),OT(2D),OT(00),OT(00),OT(00),OT(00) ; a0 - a7 32 | db OT(01),OT(01),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00) ; a8 - af 33 | db OT(2E),OT(2E),OT(2E),OT(2E),OT(2E),OT(2E),OT(2E),OT(2E) ; b0 - b7 34 | db OT(2F),OT(2F),OT(2F),OT(2F),OT(2F),OT(2F),OT(2F),OT(2F) ; b8 - bf 35 | db 004h, 004h,OT(3A),OT(00),OT(07),OT(07), 004h, 004h ; c0 - c7 36 | db OT(12),OT(00),OT(3A),OT(00),OT(25),OT(26),OT(00),OT(00) ; c8 - cf 37 | db 004h, 004h, 004h, 004h,OT(26),OT(26), 000h,OT(00) ; d0 - d7 38 | db 006h, 006h, 006h, 006h, 006h, 006h, 006h, 006h ; d8 - df 39 | db OT(27),OT(27),OT(27),OT(27),OT(23),OT(23),OT(32),OT(32) ; e0 - e7 40 | db OT(0C),OT(0C),OT(0D),OT(27),OT(24),OT(24),OT(33),OT(33) ; e8 - ef 41 | db 00Ah, 000h, 00Ah, 00Ah,OT(00),OT(00), 004h, 004h ; f0 - f7 42 | db OT(00),OT(00),OT(00),OT(00),OT(00),OT(00), 004h, 004h ; f8 - ff 43 | db OT(02),OT(02),OT(02),OT(02),OT(02),OT(02),OT(02),OT(02) ; 100 - 107 (Intel group 1) 44 | db OT(03),OT(03),OT(03),OT(03),OT(03),OT(03),OT(03),OT(03) ; 108 - 10f 45 | db OT(37),OT(37),OT(37),OT(37),OT(37),OT(37), 000h,OT(37) ; 110 - 117 (Intel group 2) 46 | db OT(38),OT(38),OT(38),OT(38),OT(38),OT(38), 000h,OT(38) ; 118 - 11f 47 | db OT(39),OT(39),OT(39),OT(39),OT(39),OT(39), 000h,OT(39) ; 120 - 127 (Intel group 2a) 48 | db OT(02), 000h,OT(10),OT(10),OT(10),OT(10),OT(10),OT(10) ; 128 - 12f (Intel group 3) 49 | db OT(10),OT(10),OT(28),OT(0E),OT(28),OT(0E),OT(28), 000h ; 130 - 137 (Intel group 5) 50 | db OT(28),OT(29),OT(29),OT(29),OT(29),OT(29), 000h, 000h ; 138 - 13f (Intel group 6) 51 | db OT(1D),OT(1D),OT(1D),OT(1D),OT(28), 000h,OT(29),OT(1D) ; 140 - 147 (Intel group 7) 52 | db OT(13),OT(13),OT(13),OT(13),OT(13),OT(13),OT(13),OT(13) ; 148 - 14f (Coprocessor d8) 53 | db OT(15),OT(15),OT(1C),OT(1C),OT(15),OT(15),OT(15),OT(15) ; 150 - 157 54 | db OT(13), 000h,OT(13),OT(13),OT(1D),OT(19),OT(1D),OT(19) ; 158 - 15f (Coprocessor d9) 55 | db OT(1B),OT(1C), 008h, 000h, 008h, 008h, 008h, 008h ; 160 - 167 56 | db OT(18),OT(18),OT(18),OT(18),OT(18),OT(18),OT(18),OT(18) ; 168 - 16f (Coprocessor da) 57 | db OT(15),OT(15),OT(15),OT(15), 000h, 008h, 000h, 000h ; 170 - 177 58 | db OT(18), 000h,OT(18),OT(18), 000h,OT(1A), 000h,OT(1A) ; 178 - 17f (Coprocessor db) 59 | db OT(15),OT(15),OT(15),OT(15), 008h,OT(1C),OT(1C), 000h ; 180 - 187 60 | db OT(14),OT(14),OT(14),OT(14),OT(14),OT(14),OT(14),OT(14) ; 188 - 18f (Coprocessor dc) 61 | db OT(16),OT(16), 000h, 000h,OT(16),OT(16),OT(16),OT(16) ; 190 - 197 62 | db OT(14), 000h,OT(14),OT(14),OT(1D), 000h,OT(1D),OT(19) ; 198 - 19f (Coprocessor dd) 63 | db OT(1B), 000h,OT(1B),OT(1B),OT(1C),OT(1C), 000h, 000h ; 1a0 - 1a7 64 | db OT(19),OT(19),OT(19),OT(19),OT(19),OT(19),OT(19),OT(19) ; 1a8 - 1af (Coprocessor de) 65 | db OT(17),OT(17), 000h, 008h,OT(17),OT(17),OT(17),OT(17) ; 1b0 - 1b7 66 | db OT(19), 000h,OT(19),OT(19),OT(1A),OT(0F),OT(1A),OT(0F) ; 1b8 - 1bf (Coprocessor df) 67 | db 000h, 000h, 000h, 000h, 008h,OT(1C),OT(1C), 000h ; 1c0 - 1c7 68 | db OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00), 000h ; 1c8 - 1cf (Coprocessor groups) 69 | db OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00) ; 1d0 - 1d7 70 | db OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00) ; 1d8 - 1df 71 | SPARSE_BASE equ $ - optypes 72 | 73 | ;--- The rest of these are squeezed. 74 | db 0, 004h, 004h,OT(08),OT(08),OT(00),OT(00),OT(00) ;00 75 | db OT(46),OT(48),OT(47),OT(49),OT(4A),OT(4B),OT(00),OT(00) ;08 76 | db OT(00),OT(08),OT(08),OT(08),OT(08),OT(08),OT(08),OT(08) ;10 77 | db OT(08),OT(08),OT(08),OT(08),OT(08),OT(08),OT(08),OT(08) ;18 78 | if MMXSUPP 79 | db OT(08),OT(4C),OT(4E),OT(00),OT(4D),OT(4F),OT(0C),OT(0C) ;20 80 | else 81 | db OT(08),0 ,0 ,OT(00),0 ,0 ,OT(0C),OT(0C) ;20 82 | endif 83 | db OT(0C),OT(0C),OT(0C),OT(0C),OT(0C),OT(0C),OT(0C),OT(0C) ;28 84 | db OT(0C),OT(0C),OT(0C),OT(0C),OT(0C),OT(0C),OT(3B),OT(3B) ;30 85 | db OT(3B),OT(3B),OT(3B),OT(3B),OT(3B),OT(3B),OT(3B),OT(3B) ;38 86 | db OT(3B),OT(3B),OT(3B),OT(3B),OT(3B),OT(3B),OT(44),OT(44) ;40 87 | db OT(00),OT(0A),OT(3C),OT(3D),OT(45),OT(45),OT(00),OT(0A) ;48 88 | db OT(3C),OT(3D),OT(08),OT(04),OT(04),OT(07),OT(0A),OT(07) ;50 89 | db OT(07),OT(30),OT(31), 004h,OT(0A),OT(08),OT(08),OT(30) ;58 90 | db OT(31),OT(04),OT(04), 004h,OT(09),OT(09),OT(09),OT(09) ;60 91 | db OT(09),OT(09),OT(09),OT(09),OT(10),OT(10),OT(0B),OT(0B) ;68 92 | db OT(0B),OT(0B),OT(0F),OT(34),OT(02),OT(00),OT(00),OT(00) ;70 93 | db OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00),OT(00) ;78 94 | db OT(00),OT(1E) 95 | 96 | OTDATA ends 97 | 98 | P186 equ 1000h 99 | P286 equ 2000h 100 | P386 equ 3000h 101 | P486 equ 4000h 102 | P586 equ 5000h 103 | P686 equ 6000h 104 | 105 | align 2 106 | 107 | ;--- compressed table of additional information. 108 | ;--- Bits 0-11 are the offset of the mnemonics table if 109 | ;--- the corresponding item in optypes is defined via OT(); 110 | ;--- else it's a parameter for the optype processing. 111 | ;--- Bits 12-15 are the cpu which introduced this opcode. 112 | 113 | opinfo label word 114 | dw MN_ADD, MN_ADD, MN_ADD, MN_ADD ; 00 115 | dw MN_ADD, MN_ADD, MN_PUSH, MN_POP ; 04 116 | dw MN_OR, MN_OR, MN_OR, MN_OR ; 08 117 | dw MN_OR, MN_OR, MN_PUSH, 01e0h ; 0c 118 | dw MN_ADC, MN_ADC, MN_ADC, MN_ADC ; 10 119 | dw MN_ADC, MN_ADC, MN_PUSH, MN_POP ; 14 120 | dw MN_SBB, MN_SBB, MN_SBB, MN_SBB ; 18 121 | dw MN_SBB, MN_SBB, MN_PUSH, MN_POP ; 1c 122 | dw MN_AND, MN_AND, MN_AND, MN_AND ; 20 123 | dw MN_AND, MN_AND, 0001h, MN_DAA ; 24 124 | dw MN_SUB, MN_SUB, MN_SUB, MN_SUB ; 28 125 | dw MN_SUB, MN_SUB, 0101h, MN_DAS ; 2c 126 | dw MN_XOR, MN_XOR, MN_XOR, MN_XOR ; 30 127 | dw MN_XOR, MN_XOR, 0201h, MN_AAA ; 34 128 | dw MN_CMP, MN_CMP, MN_CMP, MN_CMP ; 38 129 | dw MN_CMP, MN_CMP, 0301h, MN_AAS ; 3c 130 | dw MN_INC, MN_INC, MN_INC, MN_INC ; 40 131 | dw MN_INC, MN_INC, MN_INC, MN_INC ; 44 132 | dw MN_DEC, MN_DEC, MN_DEC, MN_DEC ; 48 133 | dw MN_DEC, MN_DEC, MN_DEC, MN_DEC ; 4c 134 | dw MN_PUSH, MN_PUSH, MN_PUSH, MN_PUSH ; 50 135 | dw MN_PUSH, MN_PUSH, MN_PUSH, MN_PUSH ; 54 136 | dw MN_POP, MN_POP, MN_POP, MN_POP ; 58 137 | dw MN_POP, MN_POP, MN_POP, MN_POP ; 5c 138 | dw P186 + MN_PUSHA, P186 + MN_POPA, P186 + MN_BOUND, P286 + MN_ARPL ; 60 139 | dw P386 + 0401h, P386 + 0501h, P386 + 0010h, P386 + 0020h ; 64 140 | dw P186 + MN_PUSH, P186 + MN_IMUL, P186 + MN_PUSH, P186 + MN_IMUL ; 68 141 | dw P186 + MN_INSB, P186 + MN_INSW, P186 + MN_OUTSB, P186 + MN_OUTSW ; 6c 142 | dw MN_JO, MN_JNO, MN_JB, MN_JAE ; 70 143 | dw MN_JZ, MN_JNZ, MN_JBE, MN_JA ; 74 144 | dw MN_JS, MN_JNS, MN_JPE, MN_JPO ; 78 145 | dw MN_JL, MN_JGE, MN_JLE, MN_JG ; 7c 146 | dw 0100h, 0100h, 0000h, 0108h ; 80 147 | dw MN_TEST, MN_TEST, MN_XCHG, MN_XCHG ; 84 148 | dw MN_MOV, MN_MOV, MN_MOV, MN_MOV ; 88 149 | dw MN_MOV, MN_LEA, MN_MOV, 02f8h ; 8c 150 | dw MN_NOP, MN_XCHG, MN_XCHG, MN_XCHG ; 90 151 | dw MN_XCHG, MN_XCHG, MN_XCHG, MN_XCHG ; 94 152 | dw MN_CBW, MN_CWD, MN_CALL, MN_WAIT ; 98 153 | dw MN_PUSHF, MN_POPF, MN_SAHF, MN_LAHF ; 9c 154 | dw MN_MOV, MN_MOV, MN_MOV, MN_MOV ; a0 155 | dw MN_MOVSB, MN_MOVSW, MN_CMPSB, MN_CMPSW ; a4 156 | dw MN_TEST, MN_TEST, MN_STOSB, MN_STOSW ; a8 157 | dw MN_LODSB, MN_LODSW, MN_SCASB, MN_SCASW ; ac 158 | dw MN_MOV, MN_MOV, MN_MOV, MN_MOV ; b0 159 | dw MN_MOV, MN_MOV, MN_MOV, MN_MOV ; b4 160 | dw MN_MOV, MN_MOV, MN_MOV, MN_MOV ; b8 161 | dw MN_MOV, MN_MOV, MN_MOV, MN_MOV ; bc 162 | dw 0120h, 0120h, MN_RET, MN_RET ; c0 163 | dw MN_LES, MN_LDS, 0300h, 0300h ; c4 164 | dw P186 + MN_ENTER, P186 + MN_LEAVE, MN_RETF, MN_RETF ; c8 165 | dw MN_INT, MN_INT, MN_INTO, MN_IRET ; cc 166 | dw 0110h, 0110h, 0118h, 0118h ; d0 167 | dw MN_AAM, MN_AAD, 0000h, MN_XLATB ; d4 168 | dw 0148h, 0158h, 0168h, 0178h ; d8 169 | dw 0188h, 0198h, 01a8h, 01b8h ; dc 170 | dw MN_LOOPNZW, MN_LOOPZW, MN_LOOPW, MN_JCXZ ; e0 171 | dw MN_IN, MN_IN, MN_OUT, MN_OUT ; e4 172 | dw MN_CALL, MN_JMP, MN_JMP, MN_JMP ; e8 173 | dw MN_IN, MN_IN, MN_OUT, MN_OUT ; ec 174 | dw 0008h, 0000h, 0002h, 0006h ; f0 175 | dw MN_HLT, MN_CMC, 0128h, 0128h ; f4 176 | dw MN_CLC, MN_STC, MN_CLI, MN_STI ; f8 177 | dw MN_CLD, MN_STD, 02e0h, 0130h ; fc 178 | dw MN_ADD, MN_OR, MN_ADC, MN_SBB ; 100 179 | dw MN_AND, MN_SUB, MN_XOR, MN_CMP ; 104 180 | dw MN_ADD, MN_OR, MN_ADC, MN_SBB ; 108 181 | dw MN_AND, MN_SUB, MN_XOR, MN_CMP ; 10c 182 | dw MN_ROL, MN_ROR, MN_RCL, MN_RCR ; 110 183 | dw MN_SHL, MN_SHR, 0000h, MN_SAR ; 114 184 | dw MN_ROL, MN_ROR, MN_RCL, MN_RCR ; 118 185 | dw MN_SHL, MN_SHR, 0000h, MN_SAR ; 11c 186 | dw P186 + MN_ROL, P186 + MN_ROR, P186 + MN_RCL, P186 + MN_RCR ; 120 187 | dw P186 + MN_SHL, P186 + MN_SHR, 0000h, P186 + MN_SAR ; 124 188 | dw MN_TEST, 0000h, MN_NOT, MN_NEG ; 128 189 | dw MN_MUL, MN_IMUL, MN_DIV, MN_IDIV ; 12c 190 | dw MN_INC, MN_DEC, MN_CALL, MN_CALL ; 130 191 | dw MN_JMP, MN_JMP, MN_PUSH, 0000h ; 134 192 | dw P286 + MN_SLDT, P286 + MN_STR, P286 + MN_LLDT, P286 + MN_LTR ; 138 193 | dw P286 + MN_VERR, P286 + MN_VERW, 0000h, 0000h ; 13c 194 | dw P286 + MN_SGDT, P286 + MN_SIDT, P286 + MN_LGDT, P286 + MN_LIDT ; 140 195 | dw P286 + MN_SMSW, 0000h, P286 + MN_LMSW, P486 + MN_INVLPG ; 144 196 | dw MN_FADD, MN_FMUL, MN_FCOM, MN_FCOMP ; 148 197 | dw MN_FSUB, MN_FSUBR, MN_FDIV, MN_FDIVR ; 14c 198 | dw MN_FADD, MN_FMUL, MN_FCOM, MN_FCOMP ; 150 199 | dw MN_FSUB, MN_FSUBR, MN_FDIV, MN_FDIVR ; 154 200 | dw MN_FLD, 0000h, MN_FST, MN_FSTP ; 158 201 | dw MN_FLDENV, MN_FNLDCW, MN_FNSTENV, MN_FNSTCW ; 15c 202 | dw MN_FLD, MN_FXCH, 0308h, 0000h ; 160 203 | dw 0310h, 01c8h, 01d0h, 01d8h ; 164 204 | dw MN_FIADD, MN_FIMUL, MN_FICOM, MN_FICOMP ; 168 205 | dw MN_FISUB, MN_FISUBR, MN_FIDIV, MN_FIDIVR ; 16c 206 | dw P686 + MN_FCMOVB, P686 + MN_FCMOVE, P686 + MN_FCMOVBE, P686 + MN_FCMOVU ; 170 207 | dw 0000h, 0318h, 0000h, 0000h ; 174 208 | dw MN_FILD, 0000h, MN_FIST, MN_FISTP ; 178 209 | dw 0000h, MN_FLD, 0000h, MN_FSTP ; 17c 210 | dw P686 + MN_FCMOVNB, P686 + MN_FCMOVNE, P686 + MN_FCMOVNBE, P686 + MN_FCMOVNU ; 180 211 | dw 0320h, P686 + MN_FUCOMI, P686 + MN_FCOMI, 0000h ; 184 212 | dw MN_FADD, MN_FMUL, MN_FCOM, MN_FCOMP ; 188 213 | dw MN_FSUB, MN_FSUBR, MN_FDIV, MN_FDIVR ; 18c 214 | dw MN_FADD, MN_FMUL, 0000h, 0000h ; 190 215 | dw MN_FSUBR, MN_FSUB, MN_FDIVR, MN_FDIV ; 194 216 | dw MN_FLD, 0000h, MN_FST, MN_FSTP ; 198 217 | dw MN_FRSTOR, 0000h, MN_FNSAVE, MN_FNSTSW ; 19c 218 | dw MN_FFREE, 0000h, MN_FST, MN_FSTP ; 1a0 219 | dw P386 + MN_FUCOM, P386 + MN_FUCOMP, 0000h, 0000h ; 1a4 220 | dw MN_FIADD, MN_FIMUL, MN_FICOM, MN_FICOMP ; 1a8 221 | dw MN_FISUB, MN_FISUBR, MN_FIDIV, MN_FIDIVR ; 1ac 222 | dw MN_FADDP, MN_FMULP, 0000h, 0328h ; 1b0 223 | dw MN_FSUBRP, MN_FSUBP, MN_FDIVRP, MN_FDIVP ; 1b4 224 | dw MN_FILD, 0000h, MN_FIST, MN_FISTP ; 1b8 225 | dw MN_FBLD, MN_FILD, MN_FBSTP, MN_FISTP ; 1bc 226 | dw 0000h, 0000h, 0000h, 0000h ; 1c0 227 | dw 0330h, P686 + MN_FUCOMIP, P686 + MN_FCOMIP, 0000h ; 1c4 228 | dw MN_FLD1, MN_FLDL2T, MN_FLDL2E, MN_FLDPI ; 1c8 229 | dw MN_FLDLG2, MN_FLDLN2, MN_FLDZ, 0000h ; 1cc 230 | dw MN_F2XM1, MN_FYL2X, MN_FPTAN, MN_FPATAN ; 1d0 231 | dw MN_FXTRACT, P386 + MN_FPREM1, MN_FDECSTP, MN_FINCSTP ; 1d4 232 | dw MN_FPREM, MN_FYL2XP1, MN_FSQRT, P386 + MN_FSINCOS ; 1d8 233 | dw MN_FRNDINT, MN_FSCALE, P386 + MN_FSIN, P386 + MN_FCOS ; 1dc 234 | ;--- The rest of these are squeezed. 235 | dw 0, 0138h, 0140h, P286 + MN_LAR ;00 236 | dw P286 + MN_LSL, P286 + MN_CLTS, P486 + MN_INVD, P486 + MN_WBINVD ;04 237 | dw P386 + MN_MOV, P386 + MN_MOV, P386 + MN_MOV, P386 + MN_MOV ;08 238 | dw P386 + MN_MOV, P386 + MN_MOV, P586 + MN_WRMSR, P586 + MN_RDTSC ;0C 239 | dw P586 + MN_RDMSR, P686 + MN_CMOVO, P686 + MN_CMOVNO, P686 + MN_CMOVB ;10 240 | dw P686 + MN_CMOVAE, P686 + MN_CMOVZ, P686 + MN_CMOVNZ, P686 + MN_CMOVBE ;14 241 | dw P686 + MN_CMOVA, P686 + MN_CMOVS, P686 + MN_CMOVNS, P686 + MN_CMOVPE ;18 242 | dw P686 + MN_CMOVPO, P686 + MN_CMOVL, P686 + MN_CMOVGE, P686 + MN_CMOVLE ;1C 243 | dw P686 + MN_CMOVG 244 | if MMXSUPP 245 | dw P586 + MN_MOVD, P586 + MN_MOVQ, P586 + MN_EMMS, P586 + MN_MOVD, P586 + MN_MOVQ 246 | else 247 | dw 0, 0, 0, 0, 0 248 | endif 249 | dw P386 + MN_JO, P386 + MN_JNO ;24 250 | dw P386 + MN_JB, P386 + MN_JAE, P386 + MN_JZ, P386 + MN_JNZ ;28 251 | dw P386 + MN_JBE, P386 + MN_JA, P386 + MN_JS, P386 + MN_JNS ;2C 252 | dw P386 + MN_JPE, P386 + MN_JPO, P386 + MN_JL, P386 + MN_JGE ;30 253 | dw P386 + MN_JLE, P386 + MN_JG, P386 + MN_SETO, P386 + MN_SETNO ;34 254 | dw P386 + MN_SETB, P386 + MN_SETAE, P386 + MN_SETZ, P386 + MN_SETNZ ;38 255 | dw P386 + MN_SETBE, P386 + MN_SETA, P386 + MN_SETS, P386 + MN_SETNS ;3C 256 | dw P386 + MN_SETPE, P386 + MN_SETPO, P386 + MN_SETL, P386 + MN_SETGE ;40 257 | dw P386 + MN_SETLE, P386 + MN_SETG, P386 + MN_PUSH, P386 + MN_POP ;44 258 | dw P586 + MN_CPUID, P386 + MN_BT, P386 + MN_SHLD, P386 + MN_SHLD ;48 259 | dw P386 + MN_PUSH, P386 + MN_POP, P586 + MN_RSM, P386 + MN_BTS ;4C 260 | dw P386 + MN_SHRD, P386 + MN_SHRD, P386 + MN_IMUL, P486 + MN_CMPXCHG ;50 261 | dw P486 + MN_CMPXCHG, P386 + MN_LSS, P386 + MN_BTR, P386 + MN_LFS ;54 262 | dw P386 + MN_LGS, P386 + MN_MOVZX, P386 + MN_MOVZX, 02e8h ;58 263 | dw P386 + MN_BTC, P386 + MN_BSF, P386 + MN_BSR, P386 + MN_MOVSX ;5C 264 | dw P386 + MN_MOVSX, P486 + MN_XADD, P486 + MN_XADD, 02f0h ;60 265 | dw P486 + MN_BSWAP, P486 + MN_BSWAP, P486 + MN_BSWAP, P486 + MN_BSWAP ;64 266 | dw P486 + MN_BSWAP, P486 + MN_BSWAP, P486 + MN_BSWAP, P486 + MN_BSWAP ;68 267 | dw MN_INC, MN_DEC, P386 + MN_BT, P386 + MN_BTS ;6C 268 | dw P386 + MN_BTR, P386 + MN_BTC, P586 + MN_CMPXCHG8B, MN_POP ;70 269 | dw MN_MOV, MN_FNOP, MN_FCHS, MN_FABS ;74 270 | dw MN_FTST, MN_FXAM, P386 + MN_FUCOMPP, MN_FNENI ;78 271 | dw MN_FNDISI, MN_FNCLEX, MN_FNINIT, P286 + MN_FNSETPM ;7C 272 | dw MN_FCOMPP, MN_FNSTSW 273 | 274 | ;--- table converts unsqueezed numbers to squeezed. 275 | ;--- 1E0-2DF are extended opcodes (0F xx). 276 | 277 | 278 | sqztab label byte 279 | db 1, 2, 3, 4, 0, 0, 5, 0 ;1E0 280 | db 6, 7, 0, 0, 0, 0, 0, 0 ;1E8 281 | db 0, 0, 0, 0, 0, 0, 0, 0 ;1F0 282 | db 0, 0, 0, 0, 0, 0, 0, 0 ;1F8 283 | db 8, 9, 10, 11, 12, 0, 13, 0 ;200 284 | db 0, 0, 0, 0, 0, 0, 0, 0 ;208 285 | db 14, 15, 16, 0, 0, 0, 0, 0 ;210 286 | db 0, 0, 0, 0, 0, 0, 0, 0 ;218 287 | db 17, 18, 19, 20, 21, 22, 23, 24 ;220 288 | db 25, 26, 27, 28, 29, 30, 31, 32 ;228 289 | db 0, 0, 0, 0, 0, 0, 0, 0 ;230 290 | db 0, 0, 0, 0, 0, 0, 0, 0 ;238 291 | db 0, 0, 0, 0, 0, 0, 0, 0 ;240 292 | db 0, 0, 0, 0, 0, 0, 33, 34 ;248 293 | db 0, 0, 0, 0, 0, 0, 0, 35 ;250 294 | db 0, 0, 0, 0, 0, 0, 36, 37 ;258 295 | db 38, 39, 40, 41, 42, 43, 44, 45 ;260 296 | db 46, 47, 48, 49, 50, 51, 52, 53 ;268 297 | db 54, 55, 56, 57, 58, 59, 60, 61 ;270 298 | db 62, 63, 64, 65, 66, 67, 68, 69 ;278 299 | db 70, 71, 72, 73, 74, 75, 0, 0 ;280 300 | db 76, 77, 78, 79, 80, 81, 0, 82 ;288 301 | db 83, 84, 85, 86, 87, 88, 89, 90 ;290 302 | db 0, 0, 91, 92, 93, 94, 95, 96 ;298 303 | db 97, 98, 0, 0, 0, 0, 0, 99 ;2A0 304 | db 100,101,102,103,104,105,106,107 ;2A8 305 | db 0, 0, 0, 0, 0, 0, 0, 0 ;2B0 306 | db 0, 0, 0, 0, 0, 0, 0, 0 ;2B8 307 | db 0, 0, 0, 0, 0, 0, 0, 0 ;2C0 308 | db 0, 0, 0, 0, 0, 0, 0, 0 ;2C8 309 | db 0, 0, 0, 0, 0, 0, 0, 0 ;2D0 310 | db 0, 0, 0, 0, 0, 0, 0, 0 ;2D8 311 | 312 | ;--- 5 sparse groups 313 | 314 | db 108,109, 0, 0, 0, 0, 0, 0 ;2E0 315 | db 0, 0, 0, 0,110,111,112,113 ;2E8 316 | db 0,114, 0, 0, 0, 0, 0, 0 ;2F0 317 | db 115, 0, 0, 0, 0, 0, 0, 0 ;2F8 318 | db 116, 0, 0, 0, 0, 0, 0, 0 ;300 319 | 320 | ;--- 6 sparse fpu groups 321 | 322 | SFPGROUPS equ SPARSE_BASE + ( $ - sqztab ) 323 | SFPGROUP3 equ SFPGROUPS + 8 * 3 324 | db 117, 0, 0, 0, 0, 0, 0, 0 ;308 325 | db 118,119, 0, 0,120,121, 0, 0 ;310 326 | db 0,122, 0, 0, 0, 0, 0, 0 ;318 327 | db 123,124,125,126,127, 0, 0, 0 ;320 328 | db 0,128, 0, 0, 0, 0, 0, 0 ;328 329 | db 129, 0, 0, 0, 0, 0, 0, 0 ;330 330 | 331 | ;--- table of mnemonics that change in the presence of a WAIT 332 | ;--- instruction. 333 | 334 | wtab1 dw 0322h,0321h,0320h,0323h,015dh,019eh,0324h,015fh 335 | dw 015eh,0330h,019fh 336 | wtab2 label word 337 | dw MN_FCLEX 338 | dw MN_FDISI 339 | dw MN_FENI 340 | dw MN_FINIT 341 | dw MN_FLDCW 342 | dw MN_FSAVE 343 | dw MN_FSETPM 344 | dw MN_FSTCW 345 | dw MN_FSTENV 346 | dw MN_FSTSW 347 | dw MN_FSTSW 348 | N_WTAB equ ($ - wtab2) / 2 349 | 350 | ;--- table for operands which have a different mnemonic for 351 | ;--- their 32 bit versions (66h prefix). 352 | 353 | ltabo1 dw 098h,0a7h,099h,015ch,019ch,019eh,015eh,06dh 354 | dw 0cfh,0adh,0a5h,06fh,061h,09dh,060h,09ch 355 | dw 0cbh,0cah,0afh,0abh 356 | ltabo2 label word 357 | dw MN_CWDE 358 | dw MN_CMPSD 359 | dw MN_CDQ 360 | dw MN_FLDENVD 361 | dw MN_FRSTORD 362 | dw MN_FSAVED 363 | dw MN_FSTENVD 364 | dw MN_INSD 365 | dw MN_IRETD 366 | dw MN_LODSD 367 | dw MN_MOVSD 368 | dw MN_OUTSD 369 | dw MN_POPAD 370 | dw MN_POPFD 371 | dw MN_PUSHAD 372 | dw MN_PUSHFD 373 | dw MN_RETFD 374 | dw MN_RETFD 375 | dw MN_SCASD 376 | dw MN_STOSD 377 | N_LTABO equ ($ - ltabo2) / 2 378 | 379 | ;--- table for operands which have a different mnemonic for 380 | ;--- their 32 bit versions (67h prefix). 381 | 382 | ltaba1 dw 0e3h,0e2h,0e1h,0e1h,0e0h,0e0h 383 | ltaba2 label word 384 | dw MN_JECXZ 385 | dw MN_LOOPD 386 | dw MN_LOOPED 387 | dw MN_LOOPZD 388 | dw MN_LOOPNED 389 | dw MN_LOOPNZD 390 | N_LTABA equ ($ - ltaba2) / 2 391 | 392 | ;--- table of lockable instructions 393 | 394 | locktab label word 395 | dw 010ah,0102h,010h,011h,0108h,0100h,00h,01h 396 | dw 010ch,0104h,020h,021h,029bh,02efh,0293h,02eeh 397 | dw 028bh,02edh,0290h,0291h,02e1h,0131h,02e0h,0130h 398 | dw 012bh,012ah,0109h,0101h,08h,09h,010bh,0103h 399 | dw 018h,019h,010dh,0105h,028h,029h,02a0h,02a1h 400 | dw 086h,087h,010eh,0106h,030h,031h 401 | N_LOCK equ ($ - locktab) / 2 402 | 403 | -------------------------------------------------------------------------------- /HISTORY.TXT: -------------------------------------------------------------------------------- 1 | 2 | History 3 | 4 | 0.95e [11 January 2003] Fixed a bug in the assember. 5 | 0.95f [10 September 2003] Converted to NASM; fixed some syntax 6 | incompatibilities. 7 | 0.98 [27 October 2003] Added EMS commands and copyright conditions. 8 | 9 | ------- changes below done by japheth 10 | 11 | 0.99 [27 Septemb 2006] 12 | - bugfix: IF was not displayed correctly. 13 | - FS and GS registers displayed if cpu is 80386+. 14 | - RX displays the standard 32bit registers. 15 | - R register [value] understands the standard 32bit registers. 16 | 0.99a [28 Septemb 2006] 17 | - bugfix: JECXZ had wrong prefix (66h, should be 67h). 18 | - A and D understand the 32bit opcodes LOOP(Z|NZ|E|NE)D. 19 | 0.99b [29 Septemb 2006] 20 | - L and W now work with FAT32 drives. 21 | 0.99c [29 Septemb 2006] 22 | - RX changed. Now it toggles 16/32 bit register dump. 23 | - RN displays floating point register status. 24 | 0.99d [2 October 2006] 25 | - bugfix: RN displayed error-pointer registers wrong. 26 | 0.99e [12 October 2006] 27 | - XR command added to reallocate EMS handle. 28 | - XA command allows to allocate zero pages on EMS 4.0. 29 | - TM [0|1] added to be able to switch T to the ms-dos debug 30 | compatible behaviour (that is, T jumps into 'INT xx'). 31 | 0.99f [17 October 2006] 32 | - debug's EMS functions may work even with a "hidden" EMM. 33 | - bugfix: display of mappable pages didn't account for amount of 34 | these pages == 0. 35 | 0.99g [25 October 2006] 36 | - bugfix: U was unable to recognise [ESP] related memory operands 37 | (i.e. mov eax,[esp]). 38 | 0.99h [7 November 2006] 39 | - bugfix: R trying to display content of effective address has 40 | caused a GPF in v86-mode if this address was FFFFh of FFFDh. 41 | - IW, ID, OW and OD implemented. 42 | 0.99i [14 November 2006] 43 | - bugfix: a child PSP was created but not terminated, causing files 44 | not to be closed. It became obvious if stdin and/or stdout were 45 | redirected to files ("C:\>DEBUG >yyy") 46 | 0.99j [16 November 2006] 47 | - bugfix: using T if current instruction is an INT xx (and trace 48 | mode == 0) stopped debuggee one instruction *after* the INT (due 49 | to a x86 design weakness). 50 | - bugfix: the 0.99i bugfix had some problems on FreeDOS. 51 | 1.00 [25 November 2006] 52 | - bugfix: debuggee's psp was saved after program load only, but 53 | this has to be done every time the debugger regains control. 54 | - There is now a DPMI aware version of debug, DebugX, createable 55 | from the source. 56 | - bugfix in disassembler: RETF did not have a corresponding RETFD 57 | entry (to switch with prefix 66h) 58 | 1.01 [26 November 2006] 59 | - bugfix: MC2 didn't work. 60 | - Register names can be used anywhere where a number is expected 61 | as input. 62 | 1.02 [29 November 2006] 63 | - bugfix: 'I d' and 'O d' didn't work because the parser assumed 64 | ID and OD commands. 65 | - DebugX bugfix: T= and G= didn't work in protected-mode. 66 | - bugfix: loading a file at another location than cs:100h was not 67 | supported in versions 0.99 - 1.01. 68 | - Debugger can be loaded high. 69 | 1.03 [1 February 2007] 70 | - Debug bugfix: previous version of DEBUG.COM did not reliably reset 71 | "auto-reset" breakpoints (used for processing INTs). 72 | - DebugX: DI now works in real-mode as well. 73 | - DM command added. 74 | 1.04 [2 March 2007] 75 | - making single-step through the DOS kernel possible. 76 | 1.05 [1 April 2007] 77 | - program exit code displayed. 78 | - DM displays the PSP "name". 79 | - autorepeat for D, DX, T and U added. 80 | - DebugX: DX added. 81 | 1.06 [21 May 2007] 82 | - bugfix: SMSW/LMSW in assembler didn't accept a 32bit operand. 83 | - bugfix: OW/OD didn't accept the value parameter. 84 | - key '-' supported in E command to step backward. 85 | 1.07 [3 November 2007] 86 | - bugfix: entering ranges with upper bound was refused. 87 | - DebugX bugfix: if help cmd waited for a keypress, it displayed 88 | garbage if cpu was in protected-mode and CWSDPMI was used. 89 | - Tracing into an INT (TM 1) now works if interrupt vector points 90 | to ROM code. 91 | 1.08 [23 November 2007] 92 | - bugfix: segment prefix was lost for mnemonics without arguments 93 | (patch by Oleg O. Chukaev). 94 | 1.09 [30 December 2007] 95 | - DebugX: several bugfixes for A and U handling 32bit code segments. 96 | - bugfix: U split lines if instruction size exceeded 6. 97 | - bugfix: M didn't work with "upper bound" ranges. 98 | - DebugX change: the 32-bit variant of the LOOPx instruction was 99 | indicated by displaying ECX as first operand. Now a suffix (W/D) 100 | is attached to the opcode instead. 101 | - bugfix: A didn't choose the short (=signed) form of arith 102 | instructions (adc, add, ...) if E/AX was first operand. 103 | 1.10 [25 January 2008] 104 | - DebugX: to intercept DPMI initial switches to protected-mode, 105 | int 2Fh is now hooked later. This allows to debug applications 106 | which install their own DPMI host during initialization. 107 | - DebugX: DL understands an optional "count" argument. 108 | 1.11 [6 February 2008] 109 | - bugfix: debugger lost debuggee's HiWord(EFL) in real-mode. 110 | - bugfix: if debuggee set CR0 AM bit and EFL AC flag, an 111 | exception 11h occured in the debugger. 112 | - DebugX bugfix: G command was unable to set/restore breakpoints if 113 | HiWord(EIP) wasn't clear. 114 | - DebugX bugfix: U ignored HiWord of argument's offset part. 115 | - DebugX bugfix: E ignored HiWord of argument's offset part. 116 | - DebugX bugfix: M didn't accept first argument's offset > FFFF. 117 | - DebugX bugfix: running in NTVDM and pressing Ctrl-C while debuggee 118 | is in protected-mode no longer drops to real-mode. 119 | - DebugX: RN now renders floating point register content properly 120 | (Debug.com still just displays raw hex format for size reasons). 121 | - DebugX: DI got an optional 'count' parameter. 122 | - DebugX: D default segment part is checked if it is valid in pmode 123 | and changed to value of client's DS if no. 124 | 1.12 [14 February 2008] 125 | - bugfix: length 0 in range wasn't interpreted as 64 kB. 126 | - DebugX bugfix: E in prompt mode didn't work with 32bit offsets. 127 | - DebugX bugfix: L and W didn't work with buffer offset >= 10000h. 128 | - DebugX bugfix: Q while debuggee was in pmode caused a GPF if 129 | HiWord(EIP) or HiWord(ESP) wasn't zero. 130 | - DebugX: DI additionally displays DPMI exception vectors. 131 | - DebugX: when running in NTVDM, DEBXXVDD.DLL will be loaded, which 132 | will make L and W work with sectors on this platform. 133 | - DebugX: DM now works in protected-mode as well. 134 | - now all commands are described in DEBUG.TXT. 135 | 1.13 [27 February 2008] 136 | - Debug bugfix: L and W with sectors worked for DebugX only in v1.12. 137 | 1.14 [12 January 2009] 138 | - DebugX bugfix: 'D ip' caused a syntax error. 139 | - DebugX bugfix: if debugger stepped into an INT in protected-mode, 140 | the carry flag was cleared. 141 | - H improved. 142 | - source converted to Masm syntax. 143 | - samples in Masm syntax added. 144 | 1.15 [12 April 2009] 145 | - bugfix: in v1.04 - v1.14, restoring debuggee's interrupt vectors 146 | 23+24 caused a memory corruption (8 bytes) due to a wrong segment 147 | register value. 148 | 1.16 [20 April 2009] 149 | - bugfix: 'mnc' command was rejected. Syntax changed to 'mc n'. 150 | - bugfix: in v1.14-1.15, 'g' didn't reliably detect whether a bp was 151 | external. 152 | - bugfix: 'g' command could get confused by opcode CD 03. 153 | - DebugX bugfix: 'a' command ignored hiword of current offset in 154 | 32bit segments. 155 | - DebugX bugfix: when debuggee was in protected-mode and then 156 | terminated during execution of 'p' or 't' command, the try to 157 | restore an internal bp may have caused memory corruption. 158 | 1.17 [28 April 2009] 159 | - bugfix: R <32bit register> didn't work in v1.16. 160 | - bugfix: DPMICL16.ASM wasn't a sample for a 16bit DPMI client. 161 | - bugfix: under some conditions 'm' was silently rejected. 162 | 1.18 [18 May 2009] 163 | - DebugX bugfix: RN required a 80386 cpu. 164 | - DebugX bugfix: RN always assumed that current mode is real-mode. 165 | However, the layout of FSAVE/FRSTOR differs for protected-mode. 166 | - bugfix: 'A' command didn't accept a semi-colon right after the 167 | mnemonic (example: clc;) 168 | - if cpu is 80386+, the 32bit version of FSAVE/FRSTOR is used now, 169 | which improves display of the FPU status. 170 | - 'r' command: EFL added to 386 register display. 171 | - for FLDENV, FSTENV, FSAVE and FRSTOR, 16/32 bits variants with 172 | suffixes W/D were added: FLDENVW/FLDENVD, FSTENVW/FSTENVD, ... 173 | - DebugX: 'rm' command added to display MMX registers. 174 | - DebugX: instructions MOVD, MOVQ, EMMS added to assembler and 175 | disassembler. 176 | - layout of tables in debugtbl.inc modified to make them use 177 | symbolic constants and addresses. This allows to modify this 178 | file directly. 179 | 1.19 [18 October 2010] 180 | - DebugX bugfix: breakpoints set with G couldn't be reset if the 181 | debuggee's current mode (real-mode / protected-mode) did change 182 | inside G. 183 | 1.20 [20 October 2010] 184 | - DebugX: bugfix of v1.19 modified to navigate around a couple of 185 | CWSDPMI bugs. 186 | 1.21 [29 October 2010] 187 | - DebugX bugfix: internal breakpoints set by T or P still had 188 | problems if a mode switch occured. 189 | 1.22 [11 November 2010] 190 | - DebugX bugfix: wrong value of PSP displayed with DM if debuggee 191 | was halted in real-mode after initial switch to protected-mode. 192 | - DebugX bugfix: line assembler didn't handle PC-relative addresses 193 | correctly if source or destination was > 0xFFFF. 194 | 1.23 [15 April 2011] 195 | - bugfix 'a' command: entering a segment register name may have 196 | "terminated" debug unexpectedly. 197 | - bugfix: XS always assumed 255 EMS handles. Now it tries to get 198 | the number of EMS handles by using EMS4 function 5402h. 199 | - 'a' command: the segment prefix syntax as it is implemented by 200 | MS debug is accepted now ( which is a segment register followed 201 | by a colon ). 202 | - file makex.bat added. 203 | 1.24 [4 July 2011] 204 | - bugfix: line assembler didn't encode 32-bit addressing with SIB 205 | byte correctly in v1.23. 206 | - debug script DPMICL16.SCR added. 207 | 1.25 [8 August 2011] 208 | - 2 variants (F & G) added to makex.bat 209 | 1.26 [16.1.2020] 210 | - bugfix 'a' cmd: 'MOV sreg, mem' and 'MOV mem, sreg' needed a size. 211 | - bugfix 'xm' cmd: logical page displayed was 2 digits only. 212 | - DebugX: interrupt and exception 07 intercepted. 213 | - DebugX: int 2Fh was "rehooked" if protected-mode debuggee caused a 214 | break in real-mode. 215 | - bugfix 'xs' cmd: no of pages of just the first handle was displayed, 216 | and the handle total was not correct. 217 | 1.27 [8.11.2020] 218 | - added new variant DebugXU.COM. This version does not use int 15h, 219 | ah=87h inside the DX command, thus avoiding to disable a possibly 220 | active unreal mode. The catch is that this version's DX command won't 221 | work in V86 mode. 222 | - disassembler handles operand size prefix for one-byte "push " 223 | opcodes correctly. OTOH, for 2/4 byte "push " opcodes, the 224 | disassembler no longer displays the operand size, since the size 225 | is obvious. 226 | - if InDOS flag is set, a '!' is preceding the debugger prompt. 227 | - BIOS used when waiting for a key in help msg display. 228 | - 'e' cmd uses BIOS if InDOS flag set. 229 | 1.28 [10.3.2022] 230 | - DebugX bugfix e-cmd: used wrong offset when reading from 32-bit 231 | segments. 232 | - DebugX bugfix d-cmd: hiword(ecx) wasn't cleared, resulting in a 233 | "default" length for 32-bit segment dump > 128. 234 | - DebugX bugfix g/t/p-cmd: if debuggee is stopped in protected-mode, 235 | saved stack at debugger's PSP:[2Eh] must not be "adjusted". 236 | - added debug displays (created if _DEBUG is defined) 237 | - DebugX: int 2Fh, ax=1686h to detect mode no longer used - this makes 238 | interrupt 2Fh traceable. 239 | - bugfix 'e' cmd: don't stop input after byte '0d' has been entered. 240 | 1.29 [6.5.2022] 241 | - DebugX bugfix c/d/e/m/s-cmd: an offset beyond 0ffffh was rejected if 242 | the segment descriptor's 'default-size' flag wasn't set. 243 | - DebugX bugfix e-cmd interactive mode: offset increment and decrement 244 | was always 16-bit only. 245 | - DebugX bugfix e-cmd non-interactive mode: skip test for 16-bit wrap 246 | if segment is larger than 64 kB. 247 | - regression in debugxg. v1.28: the driver version crashed when it 248 | became active because the new mode detection code always returned 249 | status "in protected-mode". 250 | - regression in DebugX, v1.28: on rare conditions, the debugger used 251 | a wrong pointer (debuggee's SS:ESP instead of SS:SP) to clear TF on 252 | the debuggee's stack. 253 | - clear TF if child process is to be canceled ( else a "memory corrupt" 254 | error may appear in DOS ). 255 | - DebugX, e-cmd: don't use int 21h, ah=8 directly in interactive mode. 256 | - volume unlock: removed setting registers dx/bh, since useless. 257 | - DebugX: behavior of q-cmd changed if debuggee is in protected-mode. 258 | Entering 'q' at the '#' prompt will (hopefully) make the debuggee 259 | exit protected-mode and debugx's real-mode prompt '-' should appear. 260 | - DebugX: new command variant 'qq' to terminate a DPMI client that has 261 | intercepted protected-mode int 21h and refuses to quit. 262 | - another variant - DebugXV - may be created. It allows to flip video 263 | screen between debugger and debuggee. 264 | 2.00 [5.12.2022] 265 | - fixed: routine int21ah9 did use DOS, even if InDos flag was set. 266 | - fixed: reading stdin from file wasn't fully MS Debug compatible. 267 | - fixed: correctly handle tabs if output is via BIOS. 268 | - fixed L/W cmds: error msg for read/write drive was crumbled since 269 | v1.18. 270 | - ensured the correct video page is used when debugger has to display 271 | something if the InDOS flag is set AND page swapping is active. 272 | - mktables.c fix: didn't generate a valid debugtbl.inc. 273 | - added a "boot" variant of the debugger - DebugB.bin. 274 | - added a ring0 (PL0) variant of the debugger - DebugR.bin. 275 | - DI cmd may be activated for standard Debug.com. 276 | - DebugX fix: restore hooked protected-mode interrupts when client 277 | terminates. 278 | - DebugX fix: c & s cmds finally work with 32-bit offsets. 279 | - DebugX fix, e cmd: generate a GPF if no data alias can be found for 280 | a code segment ( instead of silently skip the write ). 281 | - DebugX fix: disassembly of [CS:IP] in register dump may have caused 282 | a GPF in debugger if the memory address was beyond seg limit - 3. 283 | - DebugX fix, g cmd: if multiple breakpoints with different segment 284 | parts were set in protected-mode, hazardous writes may have happened. 285 | - DebugX fix, m cmd: '$' qualifier for the source address segment was 286 | rejected. 287 | - DebugX fix, c & m cmds: if both source and destination segment parts 288 | were readonly, the scratch selector was used twice. 289 | - DebugX: added cmdline option /2. 290 | - DebugX: hook into protected-mode debug interface Int 41h and make 291 | debugger visible there. 292 | - DebugX, a & e cmd: usage of scratch descriptor for readonly segments 293 | now hidden, so the displayed address' segment part isn't changed. 294 | - DebugX, a & d cmd: default segments are no longer automatically 295 | converted to selectors during initial switch to protected-mode. 296 | - DebugX: exceptions 0dh/0eh are set/reset on debugger entry/exit. 297 | - DebugXV: stop in debugger if SYSREQ is pressed. 298 | 2.01 [7.1.2024] 299 | - fixed: addr/opsize prefixes "toggle", but just once. 300 | - fixed: debug exceptions occuring inside debug are now ignored. 301 | - fixed dm cmd: invalid last mcb no longer displayed. 302 | - added a ring0 (PL0) variant for long mode - DebugRL.bin. 303 | - DebugR(L): added bp & bc cmds. 304 | 2.02 [11.2.2024] 305 | - fixed S cmd: position display was corrupted in v2.00-v2.01. 306 | 2.50 [1.6.2024] 307 | - DebugR fix: debugger assumed a 32-bit ring0 SS register on init; 308 | if this wasn't true, a crash may have occured. 309 | - fix r cmd: the disassembler tried to show memory contents for the LEA 310 | instruction - this may have caused a GPF. 311 | - DebugX fix e cmd, prompt mode: segment part changed to scratch sel 312 | after first line in protected-mode if it was a r/o selector. 313 | - fix e cmd, prompt mode: '-' after byte input did skip that input. 314 | - fix u cmd: address size prefix 67h for string instructions. 315 | - fix n cmd: names > 128 chars may have modified debug's code seg. 316 | - fix l & q cmd: failure of debuggee termination was ignored and the 317 | command continued, leaving an orphaned debuggee in memory. 318 | - fix a cmd: regression since v1.18: "call/jmp [mem_ref]" without a size 319 | given did default to a far call/jmp. 320 | - fix u cmd: operand size prefix 66h for 8/16/32-bit relative jmps. 321 | - fix a cmd: NEar qualifier was accepted/ignored for immediate far 322 | jmp/call. 323 | - u cmd, call far [mem]: qualifiers "FAR"/"DWORD FAR" changed to 324 | "FAR16"/"FAR32". 325 | - DebugR(L): Q cmd may be activated for this variant. 326 | - cmds bp/bc accept up to 4 permanent breakpoints. 327 | - cmds bp/bc implemented, but inactive for Debug & DebugX; activated in 328 | DebugXg & DebugXv variants. 329 | - G/T/P cmds: if possible, 386 debug registers will be used to set 330 | temporary breakpoints. Active for DebugX, DebugR(L). 331 | - new cmdline options /s and /v for debugger variants that may use 332 | hardware breakpoints ( option /v not for DebugR(L) variant ). 333 | - g cmd: if a breakpoint cannot be written, the cmd is aborted. 334 | - Debug & DebugX may now be created in .exe file format. 335 | - mktables.c: creates ASMTBL.INC/DISTBL.INC instead of DEBUGTBL.INC. 336 | - cmds a, u: instruction RDTSC added. 337 | - another variant of DebugR - DebugRV, with support for V86 mode. 338 | - DebugR(V) dt cmd: optionally displays trapped ports. 339 | - DebugRV di cmd: displays IDT & IVT vectors. 340 | - DebugR rn cmd: won't run cmd if CR0.EM is set. 341 | 2.51 [17.6.2025] 342 | - fix a cmd: size qualifiers weren't fully skipped if they contained 343 | digits (near16/32, far16/32). 344 | - fix DebugR dl cmd: the debugger assumed the limit of the LDT to be 345 | <= 0xffff, hence didn't display anthing if limit was i.e. 0x10000. 346 | - fix DebugR dg/dl cmd: gates in GDT/LDT were displayed in memory 347 | descriptor format. 348 | - fix DebugB l cmd: allow 32-bit sector numbers (usepacket != 0). 349 | - DebugR vc/vt/vl cmds: vectors can be (un)trapped selectively for 350 | ring 0 and 3. 351 | - DebugXf: handle exc 0 like 1,3,0dh and 0eh first, before client; 352 | 'skip' cmd still missing! 353 | - DebugR(V): don't stop if "invalid" values in registers FS,GS are 354 | detected. 355 | - DebugB: added check if already loaded beyond conv. memory. 356 | - Debug/DebugB fix: hw bp implementation for these variants was flawed. 357 | - DebugB: as default, b cmds and hw bps activated for this variant. 358 | - DebugB: added LDebugB to load DebugB into JLM FastBoot. 359 | - DebugR: (optionally) handle exception 02 (NMI). 360 | --------------------------------------------------------------------------------