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
|
Unit jmemdosa;
{$G+} {enable 286/287 instructions }
{ Original: jmemdosa.asm ; Copyright (C) 1992, Thomas G. Lane.
Based on code contributed by Ge' Weijers. }
{ This file contains low-level interface routines to support the MS-DOS
backing store manager (jmemdos.c). Routines are provided to access disk
files through direct DOS calls, and to access XMS and EMS drivers. }
interface
uses
jmorecfg;
type
XMSDRIVER = pointer; {far} { actually a pointer to code }
type
XMScontext = packed record { registers for calling XMS driver }
ax, dx, bx : ushort;
ds_si : pointer; {far}
end;
type
EMScontext = packed record { registers for calling EMS driver }
ax, dx, bx : ushort;
ds_si : pointer; {far}
end;
{ offset is a reserved word in BASM }
function jdos_open (var handle : short {far}; const filename {: PChar}) : short;
function jdos_close (handle : short) : short;
function jdos_seek (handle : short; offs : long) : short;
function jdos_read (handle : short; buffer : pointer; {FAR}
count : ushort) : short;
function jdos_write (handle : short; buffer : pointer; {FAR}
count : ushort) : short;
procedure jxms_getdriver (var driver : XMSDRIVER);
procedure jxms_calldriver (driver : XMSDRIVER;
var ctx : XMScontext);
function jems_available : short;
procedure jems_calldriver (var ctx : EMScontext);
implementation
function jdos_open (var handle : short {far};
const filename {: PChar}) : short; assembler;
{ Create and open a temporary file }
label
open_err;
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov cx,0 { normal file attributes }
lds dx, filename { get filename pointer }
mov ah,3ch { create file }
int 21h
jc open_err { if failed, return error code }
lds bx, handle { get handle pointer }
mov word ptr [bx],ax { save the handle }
xor ax,ax { return zero for OK }
open_err:
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jdos_open }
function jdos_close (handle : short) : short; assembler;
{ Close the file handle }
label
close_err;
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov bx, handle { file handle }
mov ah,3eh { close file }
int 21h
jc close_err { if failed, return error code }
xor ax,ax { return zero for OK }
close_err:
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jdos_close }
function jdos_seek (handle : short; offs : long) : short; assembler;
{ Set file position }
label
seek_err;
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov bx, handle { file handle }
mov dx, offs.word { LS offset }
mov cx, offs.word[2] { MS offset }
mov ax,4200h { absolute seek }
int 21h
jc seek_err { if failed, return error code }
xor ax,ax { return zero for OK }
seek_err:
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jdos_seek }
function jdos_read (handle : short; buffer : pointer; {FAR}
count : ushort) : short; assembler;
{ Read from file }
label
read_ok, read_err;
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov bx, handle { file handle }
lds dx, buffer { buffer address }
mov cx, count { number of bytes }
mov ah,3fh { read file }
int 21h
jc read_err { if failed, return error code }
cmp ax, count { make sure all bytes were read }
je read_ok
mov ax,1 { else return 1 for not OK }
jmp read_err
read_ok:
xor ax,ax { return zero for OK }
read_err:
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jdos_read }
function jdos_write (handle : short; buffer : pointer; {FAR}
count : ushort) : short; assembler;
{ Write to file }
label
write_ok, write_err;
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov bx, handle { file handle }
lds dx, buffer { buffer address }
mov cx, count { number of bytes }
mov ah,40h { write file }
int 21h
jc write_err { if failed, return error code }
cmp ax, count { make sure all bytes written }
je write_ok
mov ax,1 { else return 1 for not OK }
jmp write_err
write_ok:
xor ax,ax { return zero for OK }
write_err:
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jdos_write }
procedure jxms_getdriver (var driver : XMSDRIVER); assembler;
{ Get the address of the XMS driver, or NIL if not available }
label
xmsavail, xmsavail_done;
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov ax,4300h { call multiplex interrupt with }
int 2fh { a magic cookie, hex 4300 }
cmp al,80h { AL should contain hex 80 }
je xmsavail
xor dx,dx { no XMS driver available }
xor ax,ax { return a nil pointer }
jmp xmsavail_done
xmsavail:
mov ax,4310h { fetch driver address with }
int 2fh { another magic cookie }
mov dx,es { copy address to dx:ax }
mov ax,bx
xmsavail_done:
les bx,dword ptr [bp+6] { get pointer to return value }
mov word ptr es:[bx],ax
mov word ptr es:[bx+2],dx
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jxms_getdriver }
procedure jxms_calldriver (driver : XMSDRIVER;
var ctx : XMScontext); assembler;
{ The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.}
{ These are loaded, the XMS call is performed, and the new values of the }
{ AX,DX,BX registers are written back to the context structure. }
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
les bx, ctx { get XMScontext pointer }
mov ax,word ptr es:[bx] { load registers }
mov dx,word ptr es:[bx+2]
mov si,word ptr es:[bx+6]
mov ds,word ptr es:[bx+8]
mov bx,word ptr es:[bx+4]
call dword ptr driver { call the driver }
mov cx,bx { save returned BX for a sec }
les bx, ctx { get XMScontext pointer }
mov word ptr es:[bx],ax { put back ax,dx,bx }
mov word ptr es:[bx+2],dx
mov word ptr es:[bx+4],cx
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jxms_calldriver }
function jems_available : short; assembler;
{ Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)}
label
no_ems, avail_done;
const
ASCII_device_name : packed array[0..7] of char = 'EMMXXXX0';
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
mov ax,3567h { get interrupt vector 67h }
int 21h
push cs
pop ds
mov di,000ah { check offs 10 in returned seg }
lea si, ASCII_device_name { against literal string }
mov cx,8
cld
repe cmpsb
jne no_ems
mov ax,1 { match, it's there }
jmp avail_done
no_ems: xor ax,ax { it's not there }
avail_done:
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jems_available }
procedure jems_calldriver (var ctx : EMScontext); assembler;
{ The EMScontext structure contains values for the AX,DX,BX,SI,DS registers. }
{ These are loaded, the EMS trap is performed, and the new values of the }
{ AX,DX,BX registers are written back to the context structure. }
asm
push si { save all registers for safety }
push di
push bx
push cx
push dx
push es
push ds
les bx, ctx { get EMScontext pointer }
mov ax, es:[bx].EMScontext.&ax { load registers }
mov dx, es:[bx].EMScontext.&dx
mov si, es:[bx].EMScontext.&ds_si.word
mov ds, es:[bx].EMScontext.&ds_si.word[2]
mov bx, es:[bx].EMScontext.&bx
int 67h { call the EMS driver }
mov cx,bx { save returned BX for a sec }
les bx, ctx { get EMScontext pointer }
mov es:[bx].EMScontext.&ax, ax { put back ax,dx,bx }
mov es:[bx].EMScontext.&dx, dx
mov es:[bx].EMScontext.&bx, cx
pop ds { restore registers and exit }
pop es
pop dx
pop cx
pop bx
pop di
pop si
end; { jems_calldriver }
end.
|