-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathDPMI08.ASM
381 lines (249 loc) · 8.77 KB
/
DPMI08.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
;' $Header$
title DPMI08 -- Test SIGINT 08 In DPMI Client
page 58,122
name DPMI08
COMMENT| Module Specifications
Copyright: (C) Copyright 2003 Sudley Place Software.
Segmentation: Group PGROUP:
Stack segment STACK, byte-aligned, stack, class 'prog'
Program segment CODE, byte-aligned, public, class 'prog'
Tail segment NCODE, byte-aligned, public, class 'prog'
Program derived from: None.
Original code by: Bob Smith, May, 2003.
Modifications by: None.
|
.386p
.xlist
include MASM.INC
include ASCII.INC
include DOS.INC
include PTR.INC
include DPMI.INC
include 386.INC
.list
PGROUP group STACK,CODE,NDATA,NCODE,NDATAZ
; The following segment both positions class 'prog' segments lower in
; memory than others so the first byte of the resulting .COM file is
; in the CODE segment, as well as satisfies the LINKer's need to have
; a stack segment.
STACK segment use16 byte stack 'prog' ; Start STACK segment
STACK ends ; End STACK segment
CODE segment use16 byte public 'prog' ; Start CODE segment
assume cs:PGROUP,ds:PGROUP
.xlist
include PSP.INC ; Define & skip over PSP area for .COM program
.list
INITIAL:
jmp COMSHELL ; Join initialization code
CODE ends ; End CODE segment
NDATA segment use16 para public 'prog' ; Start NDATA segment
assume ds:PGROUP
public DPMIDRV_VEC
DPMIDRV_VEC dd ? ; DPMI driver address
public OLDINT08_FVEC
OLDINT08_FVEC df ? ; Old INT 08h handler
public DPMI_HPDA,HPDA_SEG
DPMI_HPDA dw ? ; DPMI HPDA size in paras
HPDA_SEG dw ? ; DPMI HPDA segment
public LCLSEL
LCLSEL dw ? ; Local selector
public SegLim
SegLim dd ? ; Segment Limit
public LCLSTK,LCLSTKZ
LCLSTK dw (4*1024) dup (?) ; Local stack
LCLSTKZ label word
NDATA ends ; End NDATA segment
NCODE segment use16 byte public 'prog' ; Start NCODE segment
assume cs:PGROUP
public MSG_COPY
MSG_COPY db 'DPMI08 -- Version 1.00 ',CR,LF
db ' (C) Copyright 2003 Sudley Place Software. '
db ' .',CR,LF,EOS
NPPROC COMSHELL -- Shell to Create a .COM File
assume ds:PGROUP,es:PGROUP,fs:nothing,gs:nothing,ss:nothing
; Switch to local stack
lea sp,LCLSTKZ ; SS:SP ==> local stack
DOSCALL @STROUT,MSG_COPY ; Display our copyright
; Check for PDMI host
call CheckDPMI ; See if we're running under a DPMI host
jc near ptr COMSHELL_EXIT ; Jump if not present
; Re-allocate our space downwards
lea bx,ZTAIL[16-1] ; Get next available byte offset
;;;;;;; and bx,not (16-1) ; Round down
shr bx,4-0 ; Convert from bytes to paras
DOSCALL @MODMEM ; Modify memory block at ES:0 to BX paras
; Allocate space for the HPDA
mov bx,DPMI_HPDA ; Get HPDA size in paras
DOSCALL @GETMEM ; Allocate BX paras
jc short COMSHELL_EXIT ; Jump if no memory
mov HPDA_SEG,ax ; Save for later use
; Enter PM through DPMI
call EnterPM ; Enter PM through DPMI
jc short COMSHELL_EXIT ; Jump if not successful
; Test LSL on various DTEs
mov cx,1
DPMICALL @DPMI_GETLDT ; Allocate a selector
;;;;;;; jc short ??? ; Jump on error
mov LCLSEL,ax ; Save for later use
mov es,ax ; Address it
assume es:nothing ; Tell the assembler about it
mov SegLim,1024*1024 ; Set to 1MB
int 01h
push LCLSEL ; Pass the selector
push CPL0_DATA ; ... Access Rights word
PUSHD 0 ; ... Base Address
push SegLim ; ... Segment Length
call SetDTE ; Set the DTE
lsl eax,LCLSEL.EDD ; Get the Segment Limit
xor ebx,ebx ; A convenient zero
mov dl,es:[ebx].LO ; Reference it
push LCLSEL ; Pass the selector
push CPL0_STK ; ... Access Rights word
PUSHD 0 ; ... Base Address
push SegLim ; ... Segment Length
call SetDTE ; Set the DTE
lsl eax,LCLSEL.EDD ; Get the Segment Limit
xor ebx,ebx ; A convenient zero
mov dl,es:[ebx].LO ; Reference it
; Hook HW INT 08h
mov bl,08h ; Hook this one
DPMICALL @DPMI_GETPMIV ; Get PM interrupt vector
; Return with CX:EDX ==> old handler
mov OLDINT08_FVEC.FOFF,edx ; Save for later use
mov OLDINT08_FVEC.FSEL,cx ; ...
;;;;;;; mov bl,08h ; Hook this one
mov cx,cs ; Get selector
lea edx,LCL_INT08 ; CX:EDX ==> new handler
DPMICALL @DPMI_SETPMIV ; Set PM interrupt vector to CX:EDX
int 01h
COMSHELL_EXIT:
DOSCALL @EXITRC ; Return to DOS
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
COMSHELL endp ; End COMSHELL procedure
NPPROC SetDTE -- Set DTE
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
COMMENT|
Set DTE
On entry:
SS:ESP ==> DTE_STR (after lclPROLOG)
On exit:
|
lclDTE_STR struc ; Local vars
lclDTE_STR ends
argDTE_STR struc ; Arguments
argDTE_LEN dd ? ; Segment Length
argDTE_BASE dd ? ; ... Base Address
argDTE_ARW dw ? ; ... Access Rights word
argDTE_SEL dw ? ; ... Selector
argDTE_STR ends
DTE_STR struc
if (type lclDTE_STR)
DTElcl db (type lclDTE_STR) dup (?) ; Local vars
endif
dw ? ; Caller's BP
dw ? ; ... IP
DTEarg db (type argDTE_STR) dup (?) ; Arguments
DTE_STR ends
lclPROLOG <DTE_STR> ; Address local vars
pusha ; Save registers
mov bx,[ebp].DTEarg.argDTE_SEL ; Get the selector
mov cx,[ebp].DTEarg.argDTE_BASE.EHI ; Get high-order word
mov dx,[ebp].DTEarg.argDTE_BASE.ELO ; ... low-...
DPMICALL @DPMI_SSELBAS ; Set the Base Address to CX:DX
;;;;;;; mov bx,[ebp].DTEarg.argDTE_SEL ; Get the selector
mov cx,[ebp].DTEarg.argDTE_ARW ; Get A/R word
DPMICALL @DPMI_SSELARW ; Set the A/R word to CX
;;;;;;; mov bx,[ebp].DTEarg.argDTE_SEL ; Get the selector
mov cx,[ebp].DTEarg.argDTE_LEN.EHI ; Get high-order word
mov dx,[ebp].DTEarg.argDTE_LEN.ELO ; ... low-...
sub dx,1 ; Convert from length to limit
sbb cx,0 ; ...
DPMICALL @DPMI_SSELLIM ; Set the Limit to CX:DX
popa ; Restore
lclEPILOG <DTE_STR> ; Strip local vars and return
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
SetDTE endp ; End SetDTE procedure
FPPROC LCL_INT08 -- Local INT 08h Handler
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
COMMENT|
Local INT 08h handler
|
int 01h ; Call our debugger
push ebx ; Save for a moment
xor ebx,ebx ; A convenient zero
mov ss:[ebx].LO,0 ; Trigger a Stack Fault
sub esp,4*1024 ; Make room on stack for local vars
push eax
pop eax
add esp,4*1024 ; Strip stack back
pop ebx ; Restore
jmp OLDINT08_FVEC ; Continue with next handler
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
LCL_INT08 endp ; End LCL_INT08 procedure
NPPROC CheckDPMI -- Check On DPMI Services
assume ds:PGROUP,es:PGROUP,fs:nothing,gs:nothing,ss:nothing
COMMENT|
Check on DPMI services
On exit:
CF = 0 if successful
= 1 if not
|
pusha ; Save all GP registers
push es ; Save
mov ax,@DPMI_GPME ; Function code to detect DPMI servcices
int 2Fh ; Request multiplexor services
assume es:nothing ; Tell the assembler about it
; On return
; AX = 0 (if present)
; BX = flags -- Bit 0: 1 = 32-bit apps supported
; CL = CPU type (02 = 286, 03 = 386, 04 = 486, etc.)
; DH = DPMI major version # (in decimal)
; DL = ... minor ...
; SI = # paras in host private data area
; ES:DI ==> VM -> PM entry point
and ax,ax ; Izit present?
stc ; Assume not
jnz short CheckDPMIExit ; Jump if not
mov DPMIDRV_VEC.VSEG,es ; Save for later use
mov DPMIDRV_VEC.VOFF,di ; ...
mov DPMI_HPDA,si ; ...
clc ; Mark as successful
CheckDPMIExit:
pop es ; Restore
assume es:nothing ; Tell the assembler about it
popa ; ...
ret ; Return to caller
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
CheckDPMI endp ; End CHECK_DPMI procedure
NPPROC EnterPM -- Enter PM Through DPMI
assume ds:PGROUP,es:PGROUP,fs:nothing,gs:nothing,ss:nothing
COMMENT|
Enter PM through DPMI
On exit:
CF = 0 if successful
= 1 if not
|
pusha ; Save registers
; Enter PM through DPMI
mov es,HPDA_SEG ; Get segment of HPDA
assume es:nothing ; Tell the assembler about it
mov ax,@DPMI_EPM_32 ; We're a 32-bit client
call DPMIDRV_VEC ; Request entry into PM
jc short EnterPMExit ; Jump if something went wrong (note CF=1)
assume ds:PGROUP ; Tell the assembler about it
;;;;;;; assume es:PSPGRP ; ...
push ds ; Get PGROUP segment/selector
pop es ; Address it
assume es:PGROUP ; Tell the assembler about it
EnterPMExit:
popa ; Restore
ret ; Return to caller
assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
EnterPM endp ; End EnterPM procedure
NCODE ends ; End NCODE segment
NDATAZ segment use16 para public 'prog' ; Start NDATAZ segment
assume ds:PGROUP
public ZTAIL
ZTAIL label byte
NDATAZ ends ; End NDATAZ segment
MEND INITIAL ; End DPMI08 module