-
Notifications
You must be signed in to change notification settings - Fork 5
/
DAPP.ASM
392 lines (331 loc) · 7.96 KB
/
DAPP.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
382
383
384
385
386
387
388
389
390
391
392
; *******************************************************
; * *
; * Turbo Pascal Run-time Library *
; * DPMI Application Main module *
; * *
; * Copyright (c) 1988,92 Borland International *
; * *
; *******************************************************
TITLE DAPP
INCLUDE SE.ASM
DATA SEGMENT WORD PUBLIC
; Externals
EXTRN Input:BYTE,Output:BYTE,SaveInt00:DWORD
EXTRN SelectorInc:WORD,Seg0040:WORD,SegA000:WORD
EXTRN SegB000:WORD,SegB800:WORD,RealModeRegs:BYTE
EXTRN ExitProc:DWORD,PrefixSeg:WORD,HInstance:WORD
EXTRN ExitCode:WORD,ErrorAddr:DWORD,Test8086:BYTE
EXTRN SaveInt21:DWORD
DATA ENDS
; Run-time manager externals
EXTRN __AHIncr:ABS,__0040H:ABS,__A000H:ABS
EXTRN __B000H:ABS,__B800H:ABS
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE,DS:DATA
; Externals
EXTRN AssignText:NEAR,ResetText:NEAR,RewriteText:NEAR
EXTRN CloseText:NEAR,HaltTurbo:NEAR,Terminate:NEAR
; Publics
PUBLIC InitTurbo
; CS-based variables for Ctrl-Break handling
Int21Vector DD 0 ;Saved INT 21H vector
CtrlBreakFlag DB 0 ;Ctrl-Break flag
; Initialize runtime library. First instruction in any program
; is a call to this routine.
InitTurbo:
MOV DX,SEG DATA ;Initialize DS
MOV DS,DX
XOR BP,BP ;End of stack frame chain
MOV PrefixSeg,ES ;Save InitTask return values
MOV HInstance,DI
MOV AX,SP
ADD AX,4
MOV SS:pStackTop,10H ;Set stack top
MOV SS:pStackBot,AX ;Set stack bottom
MOV SS:pStackMin,AX ;Set stack low water mark
MOV AX,dpmiGetVersion ;Determine CPU type
INT DPMI
DEC CL
MOV Test8086,CL
MOV SelectorInc,__AHIncr ;Set selector increment
MOV Seg0040,__0040H ;Set predefined selectors
MOV SegA000,__A000H
MOV SegB000,__B000H
MOV SegB800,__B800H
MOV DI,OFFSET SaveInt00 ;Capture interrupt vectors
MOV SI,OFFSET SaveIntTab
MOV CX,SaveIntCnt
CLD
@@1: PUSH CX
SEGCS LODSW
MOV BL,AH ;Interrupt/exception number
MOV AH,2 ;AX = 0200H, 0202H, 0204H
INT DPMI
MOV [DI].ofs,DX
MOV [DI].seg,CX
ADD DI,4
POP CX
LOOP @@1
MOV AX,CS ;Get code segment alias
ADD AX,__AHIncr
MOV ES,AX
MOV AX,SaveInt21.ofs ;Copy saved INT 21H vector to CS
MOV ES:Int21Vector.ofs,AX
MOV AX,SaveInt21.seg
MOV ES:Int21Vector.seg,AX
MOV AX,dpmiSetExcept ;Install DIV 0 handler
MOV BL,00H
MOV DX,OFFSET Int00Handler
MOV CX,CS
INT DPMI
MOV AX,0FB43H ;If TDX is present, rely on it to
MOV BX,100H ;handle stack and GP faults
INT 2FH
CMP BX,0FB43H ;TDX present?
JE @@2 ;Yes, @@2
MOV AX,dpmiSetExcept ;Install stack fault handler
MOV BL,0CH
MOV DX,OFFSET Int0CHandler
MOV CX,CS
INT DPMI
MOV AX,dpmiSetExcept ;Install GP fault handler
MOV BL,0DH
MOV DX,OFFSET Int0DHandler
MOV CX,CS
INT DPMI
@@2: MOV AX,dpmiSetInt ;Install INT 21H handler
MOV BL,21H
MOV DX,OFFSET Int21Handler
MOV CX,CS
INT DPMI
MOV BL,23H ;Install Ctrl-Break handler
MOV SI,OFFSET Int23Handler
CALL SetRealInt
MOV BL,24H ;Install critical error handler
MOV SI,OFFSET Int24Handler
CALL SetRealInt
MOV AX,OFFSET Input ;Assign/Reset Input file
PUSH DS
PUSH AX
PUSH DS
PUSH AX
MOV AX,OFFSET ZeroString
PUSH CS
PUSH AX
PUSH CS
CALL AssignText
PUSH CS
CALL ResetText
MOV AX,OFFSET Output ;Assign/Rewrite Output file
PUSH DS
PUSH AX
PUSH DS
PUSH AX
MOV AX,OFFSET ZeroString
PUSH CS
PUSH AX
PUSH CS
CALL AssignText
PUSH CS
CALL RewriteText
MOV ExitProc.ofs,OFFSET ExitTurbo ;Install exit procedure
MOV ExitProc.seg,CS
RETF ;Back to main program
; Set real mode interrupt
; In BL = Interrupt number
; SI = Handler offset
SetRealInt:
MOV AX,dpmiGetRMCB ;Create real mode call-back
MOV DI,OFFSET RealModeRegs
PUSH DS
POP ES
PUSH CS
POP DS
INT DPMI
PUSH ES
POP DS
MOV AX,dpmiSetRealInt ;Set real mode interrupt
INT DPMI
RET
; Runtime library exit procedure. This is the last exit procedure to
; get executed when an application terminates.
ExitTurbo:
MOV AX,OFFSET Input ;Close Input file
PUSH DS
PUSH AX
PUSH CS
CALL CloseText
MOV AX,OFFSET Output ;Close Output file
PUSH DS
PUSH AX
PUSH CS
CALL CloseText
MOV DI,OFFSET SaveInt00 ;Restore interrupt vectors
MOV SI,OFFSET SaveIntTab
MOV CX,SaveIntCnt
CLD
@@1: PUSH CX
SEGCS LODSW
MOV BL,AH
MOV AH,2
INC AX ;AX = 0201H, 0203H, 0205H
MOV DX,[DI].ofs
MOV CX,[DI].seg
INT DPMI
ADD DI,4
POP CX
LOOP @@1
RETF
; Divide by zero exception handler
Int00Handler:
PUSH AX
MOV AX,200
JMP SHORT Exception
; Stack fault exception handler
Int0CHandler:
PUSH AX
MOV AX,202
JMP SHORT Exception
; General protection fault handler
Int0DHandler:
PUSH AX
MOV AX,216
; Common exception handler. Saves off the error code and error address
; and modifies the exception handler stack frame to return to the
; ExceptHalt routine.
Exception:
PUSH DS
PUSH BP
MOV BP,SEG DATA
MOV DS,BP
MOV BP,SP
MOV ExitCode,AX
MOV AX,[BP+12].ofs
MOV ErrorAddr.ofs,AX
MOV AX,[BP+12].seg
MOV ErrorAddr.seg,AX
MOV [BP+12].ofs,OFFSET ExceptHalt
MOV [BP+12].seg,CS
CMP [BP+18].ofs,1024
JAE @@1
MOV [BP+18].ofs,1024
@@1: POP BP
POP DS
POP AX
RETF
; Here on return from exception handler. Restores the error code and
; error address and terminates the application.
ExceptHalt:
MOV AX,SEG DATA
MOV DS,AX
MOV AX,ExitCode
MOV CX,ErrorAddr.ofs
MOV BX,ErrorAddr.seg
JMP Terminate
; INT 21H handler. DPMI does not allow a Ctrl-Break handler to terminate
; an application, so the Ctrl-Break handler sets a flag which is then
; checked in this INT 21H hook.
Int21Handler:
STI ;Re-enable interrupts
PUSHF ;Chain to original INT 21H handler
CALL Int21Vector
PUSHF ;Save flags
CMP CtrlBreakFlag,0 ;Ctrl-Break detected?
JNE @@1 ;Yes, @@1
POPF ;Restore flags
RETF 2 ;Return
@@1: MOV AX,CS ;Get code segment alias
ADD AX,__AHIncr
MOV DS,AX
MOV DS:CtrlBreakFlag,0 ;Clear Ctrl-Break flag
MOV AX,255 ;Terminate application
JMP HaltTurbo
; Ctrl-Break interrupt handler. Control arrives here through a real mode
; call-back when DOS detects a Ctrl-C or Ctrl-Break. Since a Ctrl-Break
; handler is not allowed to terminate an application under DPMI, the
; handler sets a flag which is then checked by the INT 21H hook.
Int23Handler:
CALL RealModeIRET ;Simulate real mode IRET
MOV AX,CS ;Get code segment alias
ADD AX,__AHIncr
MOV DS,AX
MOV DS:CtrlBreakFlag,1 ;Set Ctrl-Break flag
IRET ;Return from call-back
; Critical error interrupt handler. Control arrives here when DOS
; encounters a critical error. The handler converts the critical error
; code to a Turbo Pascal I/O error code.
Int24Handler:
MOV AH,54H ;Dummy function call to get DOS
INT 21H ;into a stable state
ADD SI,6 ;Discard IRET from real mode stack
CLD
LODSW ;Pop AX from real mode stack
MOV DX,ES:[DI].realDI.w0 ;Get critical error code
AND DX,1FH ;Return AX=150..181
ADD DX,150
CMP AH,39H ;DOS 2.0 style function?
JAE @@1 ;Yes, @@1
MOV DX,0FFFFH ;Return AX=0FFFFH
@@1: MOV ES:[DI].realAX.w0,DX ;Save return AX
LODSW ;Restore other registers
MOV ES:[DI].realBX.w0,AX
LODSW
MOV ES:[DI].realCX.w0,AX
LODSW
MOV ES:[DI].realDX.w0,AX
LODSW
MOV ES:[DI].realSI.w0,AX
LODSW
MOV ES:[DI].realDI.w0,AX
LODSW
MOV ES:[DI].realBP.w0,AX
LODSW
MOV ES:[DI].realDS,AX
LODSW
MOV ES:[DI].realES,AX
ADD ES:[DI].realSP,24 ;Adjust real mode SP
CALL RealModeIRET ;Simulate real mode IRET
OR ES:[DI].realFlags,1 ;Set CF in return flags
IRET ;Return from call-back
; Simulate an IRET in a real mode call-back
RealModeIRET:
CLD
LODSW
MOV ES:[DI].realIP,AX
LODSW
MOV ES:[DI].realCS,AX
LODSW
MOV ES:[DI].realFlags,AX
ADD ES:[DI].realSP,6
RET
; Saved interrupt and exception numbers. The first byte of each entry
; is the low byte of the 02xxH DPMI function code to use when modifying
; the vector. 0 means real mode interrupt, 2 means protected mode
; exception, and 4 means protected mode interrupt.
SaveIntTab LABEL BYTE
DB 2,00H
DB 4,02H
DB 2,0CH
DB 2,0DH
DB 4,1BH
DB 4,21H
DB 0,23H
DB 0,24H
DB 4,34H
DB 4,35H
DB 4,36H
DB 4,37H
DB 4,38H
DB 4,39H
DB 4,3AH
DB 4,3BH
DB 4,3CH
DB 4,3DH
DB 4,3EH
DB 4,3FH
DB 4,75H
SaveIntCnt EQU ($-SaveIntTab)/2
; Empty string
ZeroString DB 0
CODE ENDS
END