1; 2; jmemdosa.asm 3; 4; Copyright (C) 1992, Thomas G. Lane. 5; This file is part of the Independent JPEG Group's software. 6; For conditions of distribution and use, see the accompanying README file. 7; 8; This file contains low-level interface routines to support the MS-DOS 9; backing store manager (jmemdos.c). Routines are provided to access disk 10; files through direct DOS calls, and to access XMS and EMS drivers. 11; 12; This file should assemble with Microsoft's MASM or any compatible 13; assembler (including Borland's Turbo Assembler). If you haven't got 14; a compatible assembler, better fall back to jmemansi.c or jmemname.c. 15; 16; To minimize dependence on the C compiler's register usage conventions, 17; we save and restore all 8086 registers, even though most compilers only 18; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return 19; values, which everybody returns in AX. 20; 21; Based on code contributed by Ge' Weijers. 22; 23 24JMEMDOSA_TXT segment byte public 'CODE' 25 26 assume cs:JMEMDOSA_TXT 27 28 public _jdos_open 29 public _jdos_close 30 public _jdos_seek 31 public _jdos_read 32 public _jdos_write 33 public _jxms_getdriver 34 public _jxms_calldriver 35 public _jems_available 36 public _jems_calldriver 37 38; 39; short far jdos_open (short far * handle, char far * filename) 40; 41; Create and open a temporary file 42; 43_jdos_open proc far 44 push bp ; linkage 45 mov bp,sp 46 push si ; save all registers for safety 47 push di 48 push bx 49 push cx 50 push dx 51 push es 52 push ds 53 mov cx,0 ; normal file attributes 54 lds dx,dword ptr [bp+10] ; get filename pointer 55 mov ah,3ch ; create file 56 int 21h 57 jc open_err ; if failed, return error code 58 lds bx,dword ptr [bp+6] ; get handle pointer 59 mov word ptr [bx],ax ; save the handle 60 xor ax,ax ; return zero for OK 61open_err: pop ds ; restore registers and exit 62 pop es 63 pop dx 64 pop cx 65 pop bx 66 pop di 67 pop si 68 pop bp 69 ret 70_jdos_open endp 71 72 73; 74; short far jdos_close (short handle) 75; 76; Close the file handle 77; 78_jdos_close proc far 79 push bp ; linkage 80 mov bp,sp 81 push si ; save all registers for safety 82 push di 83 push bx 84 push cx 85 push dx 86 push es 87 push ds 88 mov bx,word ptr [bp+6] ; file handle 89 mov ah,3eh ; close file 90 int 21h 91 jc close_err ; if failed, return error code 92 xor ax,ax ; return zero for OK 93close_err: pop ds ; restore registers and exit 94 pop es 95 pop dx 96 pop cx 97 pop bx 98 pop di 99 pop si 100 pop bp 101 ret 102_jdos_close endp 103 104 105; 106; short far jdos_seek (short handle, long offset) 107; 108; Set file position 109; 110_jdos_seek proc far 111 push bp ; linkage 112 mov bp,sp 113 push si ; save all registers for safety 114 push di 115 push bx 116 push cx 117 push dx 118 push es 119 push ds 120 mov bx,word ptr [bp+6] ; file handle 121 mov dx,word ptr [bp+8] ; LS offset 122 mov cx,word ptr [bp+10] ; MS offset 123 mov ax,4200h ; absolute seek 124 int 21h 125 jc seek_err ; if failed, return error code 126 xor ax,ax ; return zero for OK 127seek_err: pop ds ; restore registers and exit 128 pop es 129 pop dx 130 pop cx 131 pop bx 132 pop di 133 pop si 134 pop bp 135 ret 136_jdos_seek endp 137 138 139; 140; short far jdos_read (short handle, void far * buffer, unsigned short count) 141; 142; Read from file 143; 144_jdos_read proc far 145 push bp ; linkage 146 mov bp,sp 147 push si ; save all registers for safety 148 push di 149 push bx 150 push cx 151 push dx 152 push es 153 push ds 154 mov bx,word ptr [bp+6] ; file handle 155 lds dx,dword ptr [bp+8] ; buffer address 156 mov cx,word ptr [bp+12] ; number of bytes 157 mov ah,3fh ; read file 158 int 21h 159 jc read_err ; if failed, return error code 160 cmp ax,word ptr [bp+12] ; make sure all bytes were read 161 je read_ok 162 mov ax,1 ; else return 1 for not OK 163 jmp short read_err 164read_ok: xor ax,ax ; return zero for OK 165read_err: pop ds ; restore registers and exit 166 pop es 167 pop dx 168 pop cx 169 pop bx 170 pop di 171 pop si 172 pop bp 173 ret 174_jdos_read endp 175 176 177; 178; short far jdos_write (short handle, void far * buffer, unsigned short count) 179; 180; Write to file 181; 182_jdos_write proc far 183 push bp ; linkage 184 mov bp,sp 185 push si ; save all registers for safety 186 push di 187 push bx 188 push cx 189 push dx 190 push es 191 push ds 192 mov bx,word ptr [bp+6] ; file handle 193 lds dx,dword ptr [bp+8] ; buffer address 194 mov cx,word ptr [bp+12] ; number of bytes 195 mov ah,40h ; write file 196 int 21h 197 jc write_err ; if failed, return error code 198 cmp ax,word ptr [bp+12] ; make sure all bytes written 199 je write_ok 200 mov ax,1 ; else return 1 for not OK 201 jmp short write_err 202write_ok: xor ax,ax ; return zero for OK 203write_err: pop ds ; restore registers and exit 204 pop es 205 pop dx 206 pop cx 207 pop bx 208 pop di 209 pop si 210 pop bp 211 ret 212_jdos_write endp 213 214 215; 216; void far jxms_getdriver (XMSDRIVER far *) 217; 218; Get the address of the XMS driver, or NULL if not available 219; 220_jxms_getdriver proc far 221 push bp ; linkage 222 mov bp,sp 223 push si ; save all registers for safety 224 push di 225 push bx 226 push cx 227 push dx 228 push es 229 push ds 230 mov ax,4300h ; call multiplex interrupt with 231 int 2fh ; a magic cookie, hex 4300 232 cmp al,80h ; AL should contain hex 80 233 je xmsavail 234 xor dx,dx ; no XMS driver available 235 xor ax,ax ; return a nil pointer 236 jmp short xmsavail_done 237xmsavail: mov ax,4310h ; fetch driver address with 238 int 2fh ; another magic cookie 239 mov dx,es ; copy address to dx:ax 240 mov ax,bx 241xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value 242 mov word ptr es:[bx],ax 243 mov word ptr es:[bx+2],dx 244 pop ds ; restore registers and exit 245 pop es 246 pop dx 247 pop cx 248 pop bx 249 pop di 250 pop si 251 pop bp 252 ret 253_jxms_getdriver endp 254 255 256; 257; void far jxms_calldriver (XMSDRIVER, XMScontext far *) 258; 259; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers. 260; These are loaded, the XMS call is performed, and the new values of the 261; AX,DX,BX registers are written back to the context structure. 262; 263_jxms_calldriver proc far 264 push bp ; linkage 265 mov bp,sp 266 push si ; save all registers for safety 267 push di 268 push bx 269 push cx 270 push dx 271 push es 272 push ds 273 les bx,dword ptr [bp+10] ; get XMScontext pointer 274 mov ax,word ptr es:[bx] ; load registers 275 mov dx,word ptr es:[bx+2] 276 mov si,word ptr es:[bx+6] 277 mov ds,word ptr es:[bx+8] 278 mov bx,word ptr es:[bx+4] 279 call dword ptr [bp+6] ; call the driver 280 mov cx,bx ; save returned BX for a sec 281 les bx,dword ptr [bp+10] ; get XMScontext pointer 282 mov word ptr es:[bx],ax ; put back ax,dx,bx 283 mov word ptr es:[bx+2],dx 284 mov word ptr es:[bx+4],cx 285 pop ds ; restore registers and exit 286 pop es 287 pop dx 288 pop cx 289 pop bx 290 pop di 291 pop si 292 pop bp 293 ret 294_jxms_calldriver endp 295 296 297; 298; short far jems_available (void) 299; 300; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs) 301; 302_jems_available proc far 303 push si ; save all registers for safety 304 push di 305 push bx 306 push cx 307 push dx 308 push es 309 push ds 310 mov ax,3567h ; get interrupt vector 67h 311 int 21h 312 push cs 313 pop ds 314 mov di,000ah ; check offs 10 in returned seg 315 lea si,ASCII_device_name ; against literal string 316 mov cx,8 317 cld 318 repe cmpsb 319 jne no_ems 320 mov ax,1 ; match, it's there 321 jmp short avail_done 322no_ems: xor ax,ax ; it's not there 323avail_done: pop ds ; restore registers and exit 324 pop es 325 pop dx 326 pop cx 327 pop bx 328 pop di 329 pop si 330 ret 331 332ASCII_device_name db "EMMXXXX0" 333 334_jems_available endp 335 336 337; 338; void far jems_calldriver (EMScontext far *) 339; 340; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers. 341; These are loaded, the EMS trap is performed, and the new values of the 342; AX,DX,BX registers are written back to the context structure. 343; 344_jems_calldriver proc far 345 push bp ; linkage 346 mov bp,sp 347 push si ; save all registers for safety 348 push di 349 push bx 350 push cx 351 push dx 352 push es 353 push ds 354 les bx,dword ptr [bp+6] ; get EMScontext pointer 355 mov ax,word ptr es:[bx] ; load registers 356 mov dx,word ptr es:[bx+2] 357 mov si,word ptr es:[bx+6] 358 mov ds,word ptr es:[bx+8] 359 mov bx,word ptr es:[bx+4] 360 int 67h ; call the EMS driver 361 mov cx,bx ; save returned BX for a sec 362 les bx,dword ptr [bp+6] ; get EMScontext pointer 363 mov word ptr es:[bx],ax ; put back ax,dx,bx 364 mov word ptr es:[bx+2],dx 365 mov word ptr es:[bx+4],cx 366 pop ds ; restore registers and exit 367 pop es 368 pop dx 369 pop cx 370 pop bx 371 pop di 372 pop si 373 pop bp 374 ret 375_jems_calldriver endp 376 377JMEMDOSA_TXT ends 378 379 end 380