I wanted to debug startup of a 16-bit DOS driver on 32-bit Windows 10 with NTVDM, however attempts to attach debugger / Time Travel Debugging Trace to NTVDM startup process was triggering access violations and causing NTVDM.exe to crash. Once NTVDM had started I could attach debugger fine, but was missing the driver startup code I wanted to capture.
MS-DOS 6.00 added a feature where F8 could be pressed to run autoexec.bat/config.sys entries one line at a time, but I haven’t found an alternative that works with c:\windows\system32\config.nt in Windows.
In this case using Microsoft Macro Assmbler built this driver with the following commands:
masm wait.asm
link wait
exe2bin wait.exe wait.sys
xcopy wait.sys C:\windows\system32
The code is here, this can also be used a template for a simple MS-DOS driver.
; *******************************************************************
; * Press Any Key To Continue DRIVER *
; *******************************************************************
cseg segment para public 'code'
wait proc far
assume cs:cseg,es:cseg,ds:cseg
; *******************************************************************
; * MAIN PROCEDURE CODE *
; *******************************************************************
begin:
; *******************************************************************
; * DEVICE HEADER - REQUIRED BY DOS *
; *******************************************************************
next_dev dd -1 ; no other device drivers
attribute dw 8000h ; character device
strategy dw dev_strategy ; address of 1st dos call
interrupt dw dev_interrupt ; address of 2nd dos call
dev_name db 'WAIT$ ' ; name of the driver
; *******************************************************************
; * WORK SPACE FOR THE DEVICE DRIVER *
; *******************************************************************
rh_ofs dw ? ; request header offset
rh_seg dw ? ; request header segment
msg1 db 'Waiting...'
db 0dh,0ah,'$'
seconds db 0
counter db 0
crlf db 0dh,0ah,'$'
; *******************************************************************
; * THE STRATEGY PROCEDURE *
; *******************************************************************
dev_strategy: ; first call from DOS
mov cs:rh_seg,es ; save request header ptr segment
mov cs:rh_ofs,bx ; save request header ptr offset
ret
; *******************************************************************
; * THE INTERRUPT PROCEDURE *
; *******************************************************************
dev_interrupt: ; second call from DOS
cld ; save machine state on entry
push ds
push es
push ax
push bx
push cx
push dx
push di
push si
; perform branch based on the command passed in the req header
mov al,es:[bx]+2 ; get command code
cmp al,0 ; check for 0
jnz exit3 ; no - exit go to error exit
rol al,1 ; get offset into table
lea di,cmdtab ; get address of command table
mov ah,0 ; clear hi order
add di,ax ; add offset
jmp word ptr[di] ; jump indirect
; command table
; the command code field of the static request
; field contains the function to be performed
cmdtab label byte ;
dw init ; initialization
; *******************************************************************
; * LOCAL PROCEDURES *
; *******************************************************************
initial proc near
lea dx,msg1 ; initialization
mov ah,9 ; message
int 21h ; dos call
mov al,30 ; number of seconds to wait
call sleep
ret ; return
initial endp
; *******************************************************************
; * DOS COMMAND PROCESSING *
; *******************************************************************
;command 0 initialization
init: call initial ; display a message
lea ax,exit ; get end address (offset)
mov es:[bx]+0eh,ax ; store offset address
push cs ; get end
pop ax ; address (segment)
mov es:[bx]+10h,ax ; store in break address
jmp exit2
; *******************************************************************
; * ERROR EXIT *
; *******************************************************************
; Set the done flag, error flag, and unknown command error code
exit3: mov es:word ptr 3[bx],8103h
jmp exit1 ; restore environment
; *******************************************************************
; * COMMON EXIT *
; *******************************************************************
; common exits fall thru code
; 2 sets status to done and no error
; 1 restore callers es:bx
; 0 restore machine state and exit
exit2: ; set done flag and no error
mov es:word ptr 3[bx],0100h
exit1: mov bx,cs:rh_ofs ; restore req hdr to bx and es
mov es,cs:rh_seg ; as saved by dev_Strategy
exit0: pop si ; restore all registers
pop di
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
ret
exit:
; *******************************************************************
; * END OF PROGRAM *
; *******************************************************************
wait endp
sleep proc near
wait_for_al_seconds:
wait_loop:
push ax ; save our counter (al)
mov [counter],al
loop_top:
mov ah,2
int 1ah ; get time
mov ah, [seconds] ; retrieve last good value
cmp ah, dh ; is it same as last good value?
jz loop_top ; yup, ignore it, loop again!
mov [seconds], dh ; save seconds
; display counter - can handle range of 0-99
mov al, [counter] ; retrieve counter
cbw ; set AH to 0
mov dl, 10
div dl ; Divides AX by 10: quotient in al, remainder in ah
add ax, "00"
mov dx, ax
mov ah, 02h ; Display 1st digit of counter
int 21h
mov dl, dh
int 21h ; Display 2nd digit of counter
lea dx,crlf ; display carriage return
mov ah,9
int 21h
pop ax
dec al ; decrease al by one (does not set flags!!)
or al,al ; set flags
jnz wait_loop ; al=0? nope, around we go again!
ret ;
sleep endp
cseg ends
end begin
; that's all folks!
Now we can add line to C:\Windows\System32\config.nt to load our driver where we want it to pause:
DEVICE=%SystemRoot%\System32\wait.sys
To test all existing ntvdm.exe process must be terminated, as config.sys is only loaded when a new ntvdm.exe instance is created. Now when launching a 16-bit DOS application you will see a count down for 30 seconds when this line of config.nt has been hit:
I need your help. an executable from win7 wont run on win10 on an industrial PC from siemens but WILL run on my laptop. event viewer etc. not showing any glaring errors. my customer is paying me, ill pay you.