Category : Files from Magazines
Archive   : PJ91.ZIP
Filename : EMS.ASM

 
Output of file : EMS.ASM contained in archive : PJ91.ZIP
title expanded memory interace
include asm.inc

public ems_exchange
public ems_in
public ems_out

EMS_MAX equ 1024 ; (must be multiple of 8)
NULL_EMS equ 0

move_source_dest_struct struc ; from "official" LIM EMS 4.0 Spec - page 3-87
region_length dd ?
source_memory_type db ?
source_handle dw ?
source_initial_offset dw ?
source_initial_seg_page dw ?
dest_memory_type db ?
dest_handle dw ?
dest_initial_offset dw ?
dest_initial_seg_page dw ?
move_source_dest_struct ends


XIB segment word public 'DATA' ; enable exit intercept during
XIB ends ; intialization
XI segment word public 'DATA'
dw enable_exit_intercept
XI ends
XIE segment word public 'DATA'
XIE ends

XCB segment word public 'DATA' ; always release EMS on termination
XCB ends
XC segment word public 'DATA'
dw ems_close
XC ends
XCE segment word public 'DATA'
XCE ends


.data?
ems_struc move_source_dest_struct <>

ems_count dw ? ; number of allocated pages
ems_handle dw ?

ems_ecount dw ?
ems_icount dw ?
ems_ocount dw ?

ems_version db ?
ems_flag db ?

ems_bits db EMS_MAX/8 dup(?)


.const
ertx_ems_index db 'Bad EMS index',0
ertx_ems_error db 'Error in EMS',0


.code
extn set_strerror,get_vector,enable_exit_intercept


;; do ems function
;
; exit Cf if error (sets error string)
;
do_ems_function proc
int 67h
or ah,ah
jnz def1 ; if EMS error
ret

def1: lea ax,ertx_ems_error ; *Error in EMS*
jmp set_strerror
do_ems_function endp


;; do ems raw
;
; exit Cf if error (doesn't set error string)
;
do_ems_raw proc
int 67h
or ah,ah
jnz der1 ; if EMS error
ret
der1: stc
ret
do_ems_raw endp


;; ems close
;
; uses AX,DX
;
ems_close proc
movx dx,NULL_EMS
xchg dx,ems_handle[bp]
cmpx dx,NULL_EMS
je ecl1 ;\ if EMS not in use

mov ah,45h ; deallocate pages
call do_ems_function
ecl1: ret
ems_close endp


;; ems exchange
;
; entry AX page index (1..n)
; ES:DI destination
; exit Cf if bad block or EMS error
; uses AX
;
ems_exchange proc
pushm si,ds ; adjust and set EMS page index
dec ax
mov ems_struc.dest_initial_seg_page[bp],ax

call read_move_struc
jc eex1 ; if no EMS
mov dest_handle[si],ax

movx ax,0 ; fill in move structure
mov source_memory_type[si],al
mov source_handle[si],ax
mov source_initial_offset[si],di
mov source_initial_seg_page[si],es
mov dest_memory_type[si],1
mov dest_initial_offset[si],ax

mov ax,5701h ; exchange RAM and EMS
call do_ems_function
inc ems_ecount[bp]

eex1: popm ds,si
ret
ems_exchange endp


;; ems in
;
; entry AX block index (1..n)
; ES:DI destination (no transfer if NULL)
; exit Cf if bad block or EMS error
; uses AX
;
ems_in proc
pushm cx,si,ds
dec ax ; clear index bit
js ein2 ; if bad swap index (cannot be -)
mov si,ax
mov cl,3 ; (divide bit number by 8 to select
shr si,cl ; byte)

mov cl,al ; (use the 3 least significant bits
and cl,7 ; to rotate a mask)
mov ch,10000000b
ror ch,cl
test ems_bits[bp+si],ch
jz ein2 ; if bad EMS index
xor ems_bits[bp+si],ch ; (Cf=0)

mov cx,es ; do not read EMS file if NULL output
jcxz ein1 ; if NULL destination (Cf==0)

; set structure for move memory region
mov ems_struc.source_initial_seg_page[bp],ax

call read_move_struc
jc ein1 ; if no EMS
mov source_handle[si],ax

movx ax,0
mov source_memory_type[si],1
mov source_initial_offset[si],ax
mov dest_memory_type[si],al
mov dest_handle[si],ax
mov dest_initial_offset[si],di
mov dest_initial_seg_page[si],es

mov ax,5700h ; move from EMS to RAM
call do_ems_function
inc ems_icount[bp]

ein1: popm ds,si,cx
ret

ein2: lea ax,ertx_ems_index ; *Bad EMS index*
call set_strerror
jmp ein1
ems_in endp


;; ems out
;
; entry ES:DI source
; exit AX block index (1..n)
; Cf if EMS full or EMS error
;
ems_out proc
pushm cx,si,ds
call read_move_struc ; set structure for move memory region
jc eou2 ; if no EMS
mov dest_handle[si],ax

movx ax,0
mov source_memory_type[si],al
mov source_handle[si],ax
mov source_initial_offset[si],di
mov source_initial_seg_page[si],es
mov dest_memory_type[si],1
mov dest_initial_offset[si],ax

call get_ems_index ; select next free EMS block
jc eou2 ; if EMS bit map full
mov dest_initial_seg_page[si],ax
mov cx,ax

cmp ax,ems_count[bp] ; check EMS allocation
jb eou1 ; if enough EMS pages allocated
call realloc_more_ems ; else get more ESM from driver
jc eou2 ; if EMS full

eou1: mov ax,5700h ; move from EMS to RAM
call do_ems_function
inc ems_ocount[bp]

mov ax,cx ; return EMS index (1..MAX)
inc ax

eou2: popm ds,si,cx
ret
ems_out endp


;; get ems index
;
; exit AX ems index (0..MAX-1)
; Cf if no (more) EMS
; uses CX
;
get_ems_index proc
push si
mov al,1
mov cx,EMS_MAX
lea si,ems_bits-1

even ; search ems bits for first free index
gei1: ror al,1
adc si,ZER0
test al,[bp+si]
loopnz gei1
stc
jnz gei2 ; if EMS full
or [bp+si],al

mov ax,EMS_MAX-1
sub ax,cx

gei2: pop si
ret
get_ems_index endp


;; get ems version
;
; exit AL EMS version or 0 if no EMS
; uses SI,DS
;
get_ems_version proc
mov al,67h
call get_vector
mov si,0Ah
lodsw
cmp ax,'ME'
jne gev1 ; if no EMS
lodsw
cmp ax,'XM'
jne gev1 ; if no EMS
lodsw
cmp ax,'XX'
jne gev1 ; if no EMS
lodsw
cmp ax,'0X'
jne gev1 ; if no EMS

mov ah,46h ; get EMS version
call do_ems_function
jnc gev2

gev1: movx ax,0
stc
gev2: ret
get_ems_version endp


;; read move struc
;
; exit AX EMS handle
; DS:SI "move source dest" structure
; Cf if no EMS
; note all members set to zero except region_length
;
read_move_struc proc
mov ax,ems_handle[bp]
cmpx ax,NULL_EMS
je rms2 ; if no ems

rms1: movx ds,DGROUP_SEGMENT
lea si,ems_struc
mov wptr region_length[si],BLOCK_SIZE
mov wptr region_length[si+2],ZER0
clc
ret

rms2: mov al,-1
xchg al,ems_flag[bp]
add al,-1
jc rms4 ; if previous attempt failed

call get_ems_version
mov ems_version[bp],al
cmp al,40h
jb rms4 ; if EMS missing or out of date

rms3: mov ah,43h ; get EMS handle
pushm bx,dx
mov bx,1 ; allocate just 1 page
call do_ems_raw
mov ax,dx
popm dx,bx
jc rms4 ; if no EMS available (probably)
mov ems_handle[bp],ax
mov ems_count[bp],1

cmpx ax,NULL_EMS ; reject a zero EMS handle (Cf=0)
je rms3 ; if bad handle
jmp rms1

rms4: ret
read_move_struc endp


;; realloc more ems
;
; exit Cf if no more EMS
; uses AX
;
realloc_more_ems proc
pushm bx,dx
mov bx,ems_count[bp]
inc bx
mov dx,ems_handle[bp]
mov ah,51h
call do_ems_raw
jc rme1 ; if out of EMS
mov ems_count[bp],bx
rme1: popm dx,bx
ret
realloc_more_ems endp

end


  3 Responses to “Category : Files from Magazines
Archive   : PJ91.ZIP
Filename : EMS.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/