380 lines
8.5 KiB
NASM
Executable File
380 lines
8.5 KiB
NASM
Executable File
;
|
|
; jmemdosa.asm
|
|
;
|
|
; Copyright (C) 1992, Thomas G. Lane.
|
|
; This file is part of the Independent JPEG Group's software.
|
|
; For conditions of distribution and use, see the accompanying README file.
|
|
;
|
|
; 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.
|
|
;
|
|
; This file should assemble with Microsoft's MASM or any compatible
|
|
; assembler (including Borland's Turbo Assembler). If you haven't got
|
|
; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
|
|
;
|
|
; To minimize dependence on the C compiler's register usage conventions,
|
|
; we save and restore all 8086 registers, even though most compilers only
|
|
; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return
|
|
; values, which everybody returns in AX.
|
|
;
|
|
; Based on code contributed by Ge' Weijers.
|
|
;
|
|
|
|
JMEMDOSA_TXT segment byte public 'CODE'
|
|
|
|
assume cs:JMEMDOSA_TXT
|
|
|
|
public _jdos_open
|
|
public _jdos_close
|
|
public _jdos_seek
|
|
public _jdos_read
|
|
public _jdos_write
|
|
public _jxms_getdriver
|
|
public _jxms_calldriver
|
|
public _jems_available
|
|
public _jems_calldriver
|
|
|
|
;
|
|
; short far jdos_open (short far * handle, char far * filename)
|
|
;
|
|
; Create and open a temporary file
|
|
;
|
|
_jdos_open proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
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,dword ptr [bp+10] ; get filename pointer
|
|
mov ah,3ch ; create file
|
|
int 21h
|
|
jc open_err ; if failed, return error code
|
|
lds bx,dword ptr [bp+6] ; 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
|
|
pop bp
|
|
ret
|
|
_jdos_open endp
|
|
|
|
|
|
;
|
|
; short far jdos_close (short handle)
|
|
;
|
|
; Close the file handle
|
|
;
|
|
_jdos_close proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
push si ; save all registers for safety
|
|
push di
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
mov bx,word ptr [bp+6] ; 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
|
|
pop bp
|
|
ret
|
|
_jdos_close endp
|
|
|
|
|
|
;
|
|
; short far jdos_seek (short handle, long offset)
|
|
;
|
|
; Set file position
|
|
;
|
|
_jdos_seek proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
push si ; save all registers for safety
|
|
push di
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
mov bx,word ptr [bp+6] ; file handle
|
|
mov dx,word ptr [bp+8] ; LS offset
|
|
mov cx,word ptr [bp+10] ; 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
|
|
pop bp
|
|
ret
|
|
_jdos_seek endp
|
|
|
|
|
|
;
|
|
; short far jdos_read (short handle, void far * buffer, unsigned short count)
|
|
;
|
|
; Read from file
|
|
;
|
|
_jdos_read proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
push si ; save all registers for safety
|
|
push di
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
mov bx,word ptr [bp+6] ; file handle
|
|
lds dx,dword ptr [bp+8] ; buffer address
|
|
mov cx,word ptr [bp+12] ; number of bytes
|
|
mov ah,3fh ; read file
|
|
int 21h
|
|
jc read_err ; if failed, return error code
|
|
cmp ax,word ptr [bp+12] ; make sure all bytes were read
|
|
je read_ok
|
|
mov ax,1 ; else return 1 for not OK
|
|
jmp short 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
|
|
pop bp
|
|
ret
|
|
_jdos_read endp
|
|
|
|
|
|
;
|
|
; short far jdos_write (short handle, void far * buffer, unsigned short count)
|
|
;
|
|
; Write to file
|
|
;
|
|
_jdos_write proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
push si ; save all registers for safety
|
|
push di
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
mov bx,word ptr [bp+6] ; file handle
|
|
lds dx,dword ptr [bp+8] ; buffer address
|
|
mov cx,word ptr [bp+12] ; number of bytes
|
|
mov ah,40h ; write file
|
|
int 21h
|
|
jc write_err ; if failed, return error code
|
|
cmp ax,word ptr [bp+12] ; make sure all bytes written
|
|
je write_ok
|
|
mov ax,1 ; else return 1 for not OK
|
|
jmp short 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
|
|
pop bp
|
|
ret
|
|
_jdos_write endp
|
|
|
|
|
|
;
|
|
; void far jxms_getdriver (XMSDRIVER far *)
|
|
;
|
|
; Get the address of the XMS driver, or NULL if not available
|
|
;
|
|
_jxms_getdriver proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
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 short 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
|
|
pop bp
|
|
ret
|
|
_jxms_getdriver endp
|
|
|
|
|
|
;
|
|
; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
|
|
;
|
|
; 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.
|
|
;
|
|
_jxms_calldriver proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
push si ; save all registers for safety
|
|
push di
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
les bx,dword ptr [bp+10] ; 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 [bp+6] ; call the driver
|
|
mov cx,bx ; save returned BX for a sec
|
|
les bx,dword ptr [bp+10] ; 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
|
|
pop bp
|
|
ret
|
|
_jxms_calldriver endp
|
|
|
|
|
|
;
|
|
; short far jems_available (void)
|
|
;
|
|
; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
|
|
;
|
|
_jems_available proc far
|
|
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 short 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
|
|
ret
|
|
|
|
ASCII_device_name db "EMMXXXX0"
|
|
|
|
_jems_available endp
|
|
|
|
|
|
;
|
|
; void far jems_calldriver (EMScontext far *)
|
|
;
|
|
; 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.
|
|
;
|
|
_jems_calldriver proc far
|
|
push bp ; linkage
|
|
mov bp,sp
|
|
push si ; save all registers for safety
|
|
push di
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push es
|
|
push ds
|
|
les bx,dword ptr [bp+6] ; get EMScontext 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]
|
|
int 67h ; call the EMS driver
|
|
mov cx,bx ; save returned BX for a sec
|
|
les bx,dword ptr [bp+6] ; get EMScontext 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
|
|
pop bp
|
|
ret
|
|
_jems_calldriver endp
|
|
|
|
JMEMDOSA_TXT ends
|
|
|
|
end
|