-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOVERXMS.ASM
executable file
·323 lines (254 loc) · 8.02 KB
/
OVERXMS.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
TITLE Turbo Pascal XMS support for loading overlays - By Wilbert van Leijen
PAGE 65, 132
LOCALS @@
Data SEGMENT Word Public
ASSUME DS:Data
; XMS block move record
XmsMoveType STRUC
BlkSize DD ?
SrcHandle DW ?
SrcOffset DD ?
DestHandle DW ?
DestOffset DD ?
XmsMoveType ENDS
; TP overlay manager record
OvrHeader STRUC
ReturnAddr DD ? ; Virtual return address
FileOfs DD ? ; Offset into overlay file
CodeSize DW ? ; Size of overlay
FixupSize DW ? ; Size of fixup table
EntryPts DW ? ; Number of procedures
CodeListNext DW ? ; Segment of next overlay
LoadSeg DW ? ; Start segment in memory
Reprieved DW ? ; Loaded in memory flag
LoadListNext DW ? ; Segment of next in load list
XmsOffset DD ? ; Offset into allocated XMS block
UserData DW 3 DUP(?)
OvrHeader ENDS
XmsDriver DD ? ; Entry point of XMS driver
ExitSave DD ? ; Pointer to previous exit proc
XmsMove XmsMoveType <>
OvrXmsHandle DW ? ; Returned by XMS driver
Extrn PrefixSeg : Word
Extrn ExitProc : DWord
Extrn OvrResult : Word
Extrn OvrCodeList : Word
Extrn OvrDosHandle : Word
Extrn OvrHeapOrg : Word
Extrn OvrReadBuf : DWord
Data ENDS
Code SEGMENT Byte Public
ASSUME CS:Code
Public OvrInitXMS
ovrIOError EQU -4
ovrNoXMSDriver EQU -7
ovrNoXMSMemory EQU -8
OvrXmsExit PROC
; Release handle and XMS memory
MOV DX, [OvrXmsHandle]
MOV AH, 10
CALL [XmsDriver]
; Restore pointer to previous exit procedure
LES AX, [ExitSave]
MOV Word Ptr [ExitProc], AX
MOV Word Ptr [ExitProc+2], ES
RETF
OvrXmsExit ENDP
AllocateXms PROC
; Determine the size of the XMS block to allocate:
; Walk the CodeListNext chain
; Store the total codesize in DX:AX
XOR AX, AX
XOR DX, DX
MOV BX, [OvrCodeList]
@@1: ADD BX, [PrefixSeg]
ADD BX, 10h
MOV ES, BX
ADD AX, ES:[OvrHeader.CodeSize]
ADC DX, 0
MOV BX, ES:[OvrHeader.CodeListNext]
OR BX, BX
JNZ @@1
; Obtain number of kilobytes to allocate
MOV BX, 1024
DIV BX
XCHG DX, AX
INC DX
; Allocate the block
MOV AH, 9
CALL [XmsDriver]
OR AX, AX
JZ @@2
MOV [OvrXmsHandle], DX
@@2: RETN
AllocateXms ENDP
; Function XmsReadFunc(OvrSeg : Word) : Integer; Far;
XmsReadFunc PROC
; Swap the code from XMS to the heap
PUSH BP
MOV BP, SP
MOV ES, [BP+6]
MOV AX, ES:[OvrHeader.CodeSize]
MOV Word Ptr [XmsMove.BlkSize], AX
XOR AX, AX
MOV Word Ptr [XmsMove.BlkSize+2], AX
MOV AX, [OvrXmsHandle]
MOV [XmsMove.SrcHandle], AX
MOV AX, Word Ptr ES:[OvrHeader.XmsOffset]
MOV Word Ptr [XmsMove.SrcOffset], AX
MOV AX, Word Ptr ES:[OvrHeader.XmsOffset+2]
MOV Word Ptr [XmsMove.SrcOffset+2], AX
XOR AX, AX
MOV [XmsMove.DestHandle], AX
MOV Word Ptr [XmsMove.DestOffset], AX
MOV AX, ES:[OvrHeader.LoadSeg]
MOV Word Ptr [XmsMove.DestOffset+2], AX
MOV AH, 11
LEA SI, XmsMove
CALL [XmsDriver]
OR AX, AX
JZ @@1
DEC AX
JMP @@2
@@1: MOV AX, ovrIOError
@@2: POP BP
RETF 2
XmsReadFunc ENDP
; Copy an overlaid unit from the heap to XMS
; If successful, carry flag is cleared
; In/Out:
; BX:DI = offset into XMS memory block
CopyUnitToXms PROC
; XMS requires that an even number of bytes is moved
MOV DX, ES:[OvrHeader.CodeSize]
TEST DX, 1
JZ @@1
INC DX
INC ES:[OvrHeader.CodeSize]
; Get the fields of the XMS block move structure
@@1: MOV Word Ptr [XmsMove.BlkSize], DX
XOR AX, AX
MOV Word Ptr [XmsMove.BlkSize+2], AX
MOV [XmsMove.SrcHandle], AX
MOV Word Ptr [XmsMove.SrcOffset], AX
MOV AX, [OvrHeapOrg]
MOV Word Ptr [XmsMove.SrcOffset+2], AX
MOV AX, [OvrXmsHandle]
MOV [XmsMove.DestHandle], AX
MOV Word Ptr [XmsMove.DestOffset], DI
MOV Word Ptr [XmsMove.DestOffset+2], BX
MOV AH, 11
LEA SI, XmsMove
CALL [XmsDriver]
; Bump code size
ADD DI, DX
ADC BX, 0
; Check return code from XMS driver
OR AX, AX
JZ @@2
CLC
RETN
@@2: STC
RETN
CopyUnitToXms ENDP
OvrXmsLoad PROC
PUSH BP
MOV BP, SP
; Walk the CodeList chain
; First segment is PrefixSeg+10h+OvrCodeList
; Push each element of overlaid unit list on the stack
; Keep the size of the linked list in CX
MOV AX, [OvrCodeList]
XOR CX, CX
@@1: ADD AX, [PrefixSeg]
ADD AX, 10h
MOV ES, AX
PUSH AX
INC CX
MOV AX, ES:[OvrHeader.CodeListNext]
OR AX, AX
JNZ @@1
; Loop:
; Pop each element of the overlaid unit list from the stack
XOR BX, BX
XOR DI, DI
@@2: POP ES
PUSH CX
MOV AX, [OvrHeapOrg]
MOV ES:[OvrHeader.LoadSeg], AX
MOV Word Ptr ES:[OvrHeader.XmsOffset+2], BX
MOV Word Ptr ES:[OvrHeader.XmsOffset], DI
; Load overlay from disk
PUSH BX
PUSH DI
PUSH ES
PUSH ES
CALL [OvrReadBuf]
POP ES
POP DI
POP BX
; Flag unit as 'unloaded'; check return code
MOV ES:[OvrHeader.LoadSeg], 0
NEG AX
JC @@3
CALL CopyUnitToXms
JC @@3
POP CX
LOOP @@2
@@3: MOV SP, BP
POP BP
RETN
OvrXMSLoad ENDP
OvrInitXMS PROC
; Make sure the file's been opened
XOR AX, AX
CMP AX, [OvrDOSHandle]
JNE @@1
DEC AX ; ovrError
JMP @@5
; Check presence of XMS driver
@@1: MOV AX, 4300h
INT 2Fh
CMP AL, 80h
JE @@2
MOV AX, ovrNoXmsDriver
JMP @@5
; Get XMS driver's entry point
@@2: MOV AX, 4310h
INT 2Fh
MOV Word Ptr [XmsDriver], BX
MOV Word Ptr [XmsDriver+2], ES
CALL AllocateXms
JNZ @@3
MOV AX, ovrNoXMSMemory
JMP @@5
; Load the overlay into XMS
@@3: CALL OvrXmsLoad
JNC @@4
; An error occurred. Release handle and XMS memory
MOV DX, [OvrXmsHandle]
MOV AH, 10
CALL [XmsDriver]
MOV AX, ovrIOError
JMP @@5
; Close file
@@4: MOV BX, [OvrDOSHandle]
MOV AH, 3Eh
INT 21h
; OvrReadBuf := XmsReadFunc
MOV Word Ptr [OvrReadBuf], Offset XmsReadFunc
MOV Word Ptr [OvrReadBuf+2], CS
; ExitSave := ExitProc
; ExitProc := OvrXmsExit
LES AX, [ExitProc]
MOV Word Ptr [ExitSave], AX
MOV Word Ptr [ExitSave+2], ES
MOV Word Ptr [ExitProc], Offset OvrXmsExit
MOV Word Ptr [ExitProc+2], CS
; Return result of initialisation
XOR AX, AX
@@5: MOV [OvrResult], AX
RETF
OvrInitXMS ENDP
Code ENDS
END