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

 
Output of file : BLOCK.ASM contained in archive : PJ91.ZIP
title block storage manager
include asm.inc

public block_alloc
public block_file_open
public block_file_read
public block_free
public block_read

BLOCK_MAX equ 512
FIRST_BLOCK equ 08000h ; block handles start at 0x8000

NULL_BLOCK equ 0
NULL_EMS equ 0
NULL_ID equ 0
NULL_SWAP equ 0

OPEN_LINK equ 0FFFFh

block_str struc
blk_forward dw ? ; forward link for LRU
blk_backward dw ? ; backward link
blk_pointer dd ? ; RAM address (or 0 if in EMS or DISK)
blk_ems_index dw ? ; EMS index
blk_swap_index dw ? ; swap file index (0 if not swapped)
blk_file_id dw ? ; file identification (0 if not in file)
blk_file_index dw ? ; file block index
blk_file_link dw ? ; blocks for each file form a list
blk_byte_count dw ? ; (file blocks may be less than 16k)
block_str ends ; (structure must be even number of bytes)


XIB segment word public 'DATA' ; initialize block manager
XIB ends
XI segment word public 'DATA'
dw block_preset
XI ends
XIE segment word public 'DATA'
XIE ends


.const
ertx_block_handle db 'Bad block handle',0
ertx_empty_file db 'Cannot map empty file',0
ertx_free_block db 'Cannot free block',0
ertx_past_eof db 'Block read past EOF',0
ertx_virtual_full db 'Virtual memory full',0


.data?
block_table dd ? ; array of block structures

ram_front dw ? ; LRU list of RAM blocks
ram_back dw ?

ems_front dw ? ; LRU list of EMS blocks
ems_back dw ?

free_front dw ? ; free handle stack
free_count dw ? ; number of free blocks

file_blocks dw ? ; # of blocks in file (see block_file_open)

.code
extn abort_if_cf,calloc,clear_strerror,ems_exchange,ems_in,swap_in
extn ems_out,free,malloc,save_most,set_strerror,swap_out,check_block_file
extn open_block_file,read_block_file,set_block_handle

page
;; access block table
;
; entry BX block handle
; exit DS:SI block table entry for handle
; Cf if bad handle
; uses AX
;
access_block_table proc
mov ax,bx
sub ax,FIRST_BLOCK
jb abt1 ; if bad handle
cmp ax,BLOCK_MAX
jae abt1 ; if bad handle
mov si,dx
mov dx,size block_str
mul dx
mov dx,si

lds si,block_table[bp]
add si,ax
ret

abt1: lea ax,ertx_block_handle ; *Bad block handle*
jmp set_strerror
access_block_table endp


;; block alloc
;
; exit AX block size in bytes
; BX block handle
; ES:DI block pointer
; Cf if no memory
;
block_alloc proc
pushm si,ds
call malloc_storage_block
jc bal2 ; if no memory

call new_block_handle
jc bal1 ; if no more block handles
mov wptr blk_pointer[si],di
mov wptr blk_pointer[si+2],es

call set_mru_ram ; set most recently used
mov ax,BLOCK_SIZE
mov blk_byte_count[si],ax
clc
jmp bal3

bal1: call free ; here when out of handles, free
bal2: movx bx,NULL_BLOCK ; storage and return error
stc

bal3: popm ds,si
ret
block_alloc endp


;; block file open
;
; entry DS:SI file name
; exit AX file size in blocks
; BX block handle
; Cf if file not found or empty
;
block_file_open proc
pushm cx,dx,di,si,ds
call check_block_file
jnc bfo4 ; if existing file

bfo1: call open_block_file
jc bfo4 ; if file not found
jcxz bfo7 ; if empty file

cmp cx,free_count[bp]
ja bfo5 ; if not enough blocks for file

mov file_blocks[bp],cx
movx cx,0

call new_file_block ; allocate first file block
jc bfo4
mov bx,ax
cmp cx,file_blocks[bp]
je bfo3 ; if file size <= 16k

bfo2: mov di,si
call new_file_block
jc bfo4
mov blk_file_link[di],si
cmp cx,file_blocks[bp]
jb bfo2

call set_block_handle ; save handle in case we open again

bfo3: mov ax,file_blocks[bp] ; return file size (Cf unchanged)

bfo4: popm ds,si,di,dx,cx
ret

bfo5: lea ax,ertx_virtual_full ; *Virtual memory full*
bfo6: call set_strerror
jmp bfo4
bfo7: lea ax,ertx_empty_file ; *Cannot map empty file*
jmp bfo6
block_file_open endp


;; block file read
;
; entry AX 16k file block number (0..n)
; BX block index
; exit DS:SI block pointer
; AX block size (<16k if last block)
; Cf if bad block index or past end of file
;
block_file_read proc
push cx
mov cx,ax
call access_block_table
jc bfr4

jcxz bfr2 ; if first block
bfr1: mov si,blk_file_link[si] ; else chase linked list to
cmp si,OPEN_LINK ; selected blk
loopne bfr1
je bfr3 ; if block number too large

bfr2: pop cx
jmp block_read_primitive

bfr3: lea ax,ertx_past_eof ; *Block read past EOF*
call set_strerror
bfr4: pop cx
ret
block_file_read endp


;; block free
;
; entry BX block index
; exit Cf if bad index (cannot free file blocks)
; uses AX,BX
;
block_free proc
pushm di,si,ds,es
call access_block_table
jc bfe5

cmp blk_file_id[si],NULL_ID ; illegal to free a file block
jne bfe6 ; if file block

les di,blk_pointer[si]
mov ax,es
or ax,di
jz bfe1 ; if not in RAM

call unlink_ram_list ; unlink block from RAM LRU list
call free ; free storage
jmp bfe3

bfe1: mov ax,blk_ems_index[si]
cmpx ax,NULL_EMS
je bfe2 ; if not in EMS

call ems_in ; free EMS block (ES:DI==NULL)
call unlink_ems_list ; unlink block from EMS LRU list
jmp bfe3

bfe2: mov ax,blk_swap_index[si]
cmpx ax,NULL_SWAP
je bfe6 ; if not in swap file (thus error)

call swap_in ; free swap block (ES:DI==NULL)

bfe3: mov bx,size block_str ; clear block table entry and
bfe4: dec bx ; leave BX==0
dec bx
mov wptr [si+bx],ZER0
jnz bfe4

mov ax,si ; link onto free block stack
xchg ax,free_front[bp]
mov blk_backward[si],ax
inc free_count[bp]

clc
bfe5: popm es,ds,si,di ; (POP xS could fault in protect mode)
ret

bfe6: lea ax,ertx_free_block ; *Cannot free block*
call set_strerror
jmp bfe5
block_free endp


;; block preset
;
; uses AX
;
block_preset proc
call save_most ; allocate block table
mov cx,BLOCK_MAX*size block_str
call calloc ; (must have NULL offset)
call abort_if_cf
mov wptr block_table[bp],di
mov wptr block_table[bp+2],es

mov ax,OPEN_LINK ; build free list
mov cx,BLOCK_MAX
mov free_count[bp],cx
lds si,block_table[bp]
mov free_front[bp],si
bps1: lea dx,[si+size block_str]
mov blk_backward[si],dx
mov blk_forward[si],ax
mov blk_file_link[si],ax
xchg dx,si
loop bps1
mov blk_backward[si-size block_str],ax

mov ram_front[bp],ax ;\initialize LRU lists for RAM and EMS
mov ram_back[bp],ax
mov ems_front[bp],ax
mov ems_back[bp],ax
ret
block_preset endp


;; block read
;
; entry BX block index
; exit AX block size
; DS:SI block pointer
; Cf if bad block or no memory
;
block_read proc
call access_block_table
jnc block_read_primitive ;\
ret ;\
block_read endp


;; block read primitive
;
; entry DS:SI block table pointer
; exit AX block size
; DS:SI block pointer
; Cf if bad block or no memory
;
block_read_primitive proc
pushm di,es
cmp wptr blk_pointer[si+2],NULL_POINTER
je brp1 ; if block is not in RAM
call reset_mru_ram ; move to front of LRU list
jmp brp5

brp1: call malloc_storage_block ; allocate storage for block
jc brp6 ; if no memory

mov ax,blk_ems_index[si] ; check if block swapped to EMS
cmpx ax,NULL_EMS
je brp2 ; if not in EMS

call ems_in ; else swap block in from EMS
jc brp8 ; if unexpected EMS error

call unlink_ems_list ; delete from EMS LRU list
mov blk_ems_index[si],NULL_EMS
jmp brp4

brp2: cmp blk_file_id[si],NULL_ID ; check if file block
je brp3 ; if not

push bx ; else read block from file
mov bx,blk_file_id[si]
mov ax,blk_file_index[si]
call read_block_file
pop bx
jc brp8 ; if error reading file
mov blk_byte_count[si],ax
jmp brp4 ; else read OK

brp3: mov ax,blk_swap_index[si] ; check if block swapped out
cmpx ax,NULL_SWAP
je brp7 ; if not swapped - bad block handle
call swap_in
jc brp8 ; if error swapping block in
mov blk_swap_index[si],NULL_SWAP

brp4: mov wptr blk_pointer[si],di ; save RAM pointer in block table
mov wptr blk_pointer[si+2],es
call set_mru_ram ; move to front of LRU list

brp5: mov ax,blk_byte_count[si] ; return RAM pointer and byte count
lds si,blk_pointer[si]
clc
brp6: popm es,di
ret

brp7: lea ax,ertx_block_handle ; *Bad block handle*
call set_strerror

brp8: call free
stc
jmp brp6
block_read_primitive endp


;; free ram block
;
; exit Cf if no RAM free
; uses AX
;
free_ram_block proc
call save_most
call get_lru_ram ; get least recently used memory block
jc frb4 ; if no blocks on LRU list

les di,blk_pointer[si] ; else file block, swap to EMS
call ems_out
jc frb2 ; if unable to swap to EMS
mov blk_ems_index[si],ax ; else save EMS page index
call set_mru_ems

frb1: call free ; free storage
jc frb4 ; if unexpected error
mov wptr blk_pointer[si],di ; (free returns with ES:DI==NULL)
mov wptr blk_pointer[si+2],es
jmp frb4

frb2: call clear_strerror ; here when EMS is full
cmp blk_file_id[si],NULL_ID ; is block file or storage?
jne frb1 ; if file block - just free its ram

mov bx,si ; try exchanging RAM block & LRU EMS
call get_lru_ems
jc frb3 ; if no EMS (SI still -> RAM block)
mov ax,blk_ems_index[si]
call ems_exchange ; (ES:DI still points to RAM block)
jc frb4 ; if exchange failed (serious error)

movx ax,NULL_EMS ; exchange EMS index and RAM pointers
xchg ax,blk_ems_index[si] ; for exchanged blocks
mov blk_ems_index[bx],ax
mov wptr blk_pointer[bx],NULL_POINTER
mov wptr blk_pointer[bx+2],NULL_POINTER
mov wptr blk_pointer[si],di
mov wptr blk_pointer[si+2],es

xchg bx,si ; set most recently used EMS block
call set_mru_ems
xchg bx,si

frb3: call swap_out ; write block to swap file
mov blk_swap_index[si],ax ; set swap index (or 0 if failure)
jnc frb1 ; if swapped OK

call set_lru_ram ; swap failed, re-link RAM block
movx bx,NULL_BLOCK
stc

frb4: ret
free_ram_block endp


;; get lru ems
;
; exit DS:SI least recently used block in EMS
; Cf if no blocks in EMS (SI unchanged)
; uses AX
;
get_lru_ems proc
mov ax,OPEN_LINK
cmp ax,ems_back[bp]
je gle2 ;\ if no EMS blocks

lds si,block_table[bp]
mov si,ems_back[bp]
cmp si,ems_front[bp]
je gle1 ; if only one EMS block

push bx
mov bx,blk_forward[si]
mov blk_backward[bx],ax
mov ems_back[bp],bx
pop bx
clc
ret

gle1: mov ems_front[bp],ax
mov ems_back[bp],ax
ret ; (Cf==0)

gle2: stc
ret
get_lru_ems endp


;; get lru ram
;
; exit DS:SI least recently used block in RAM
; Cf if no unlocked blocks in RAM
; uses AX
;
get_lru_ram proc
mov ax,OPEN_LINK
lds si,block_table[bp]
mov si,ram_back[bp]
cmp si,ax
je glr2 ; if no RAM blocks
cmp si,ram_front[bp]
je glr1 ; if only one RAM block

push bx
mov bx,blk_forward[si]
mov blk_backward[bx],ax
mov ram_back[bp],bx
pop bx
clc
ret

glr1: mov ram_front[bp],ax
mov ram_back[bp],ax
ret ; (Cf==0)

glr2: stc
ret
get_lru_ram endp


;; malloc storage block
;
; exit ES:DI storage block
; Cf if unable to allocate storage
; uses AX
;
malloc_storage_block proc
push cx
mov cx,BLOCK_SIZE ; allocate block of memory
call malloc
jnc msb1 ; if OK

call clear_strerror ; clear malloc error
call free_ram_block ; swap to EMS or disk to free ram
jc msb1 ; if too many locked blocks

call malloc ; try malloc one more time

msb1: pop cx
ret
malloc_storage_block endp


;; new block handle
;
; exit BX block handle
; DS:SI block table entry
; Cf if no free handles
; uses AX
;
new_block_handle proc
lds si,block_table[bp] ; get first block from free list
mov si,free_front[bp]
cmp si,OPEN_LINK
je nbh1 ; if no more handles
mov ax,blk_backward[si]
mov free_front[bp],ax
dec free_count[bp]

push dx ; compute handle from table offset
mov ax,si
movx dx,0
mov bx,size block_str
div bx
add ax,FIRST_BLOCK
mov bx,ax
pop dx
ret

nbh1: lea ax,ertx_virtual_full ; *Virtual memory full*
jmp set_strerror
new_block_handle endp


;; new file block
;
; entry CX block number
; DX file id
; exit AX block handle
; CX +1
; DS:SI block table entry
; Cf if no more blocks
;
new_file_block proc
push bx
call new_block_handle ; allocate block
jc nfb1 ; if no more blocks

mov blk_file_id[si],dx ; set file id and block number
mov blk_file_index[si],cx
inc cx

mov ax,OPEN_LINK ; reset links
mov blk_file_link[si],ax
mov blk_forward[si],ax
mov blk_backward[si],ax

mov ax,bx ;\
nfb1: pop bx
ret
new_file_block endp


;; reset mru ram
;
; entry DS:SI most recently used table entry
; uses AX
;
reset_mru_ram proc
cmp si,ram_front[bp]
je rmr4 ; if already most recently used

push bx
cmp si,ram_back[bp]
je rmr1 ; if least recently used

mov ax,blk_forward[si] ; delete from middle of LRU list
mov bx,blk_backward[si]
mov blk_forward[bx],ax
xchg ax,bx
mov blk_backward[bx],ax
jmp rmr2

rmr1: call get_lru_ram ; delete from back of LRU list
jc rmr3 ; if internal error
rmr2: call set_mru_ram
clc
rmr3: pop bx
rmr4: ret
reset_mru_ram endp


;; set lru ram
;
; entry DS:SI least recently used table entry
; uses AX,BX
;
set_lru_ram proc
mov ax,OPEN_LINK ; check for empty list
mov bx,si
xchg bx,ram_back[bp]
cmp bx,ax
je slr1 ; if empty list

mov blk_backward[si],ax ; else link onto back of list
mov blk_forward[si],bx
mov blk_backward[bx],si
ret

slr1: mov ram_front[bp],si ; create list with one element
mov blk_forward[si],ax
mov blk_backward[si],ax
ret
set_lru_ram endp


;; set mru ems
;
; entry DS:SI most recently used table entry
; uses AX
;
set_mru_ems proc
push bx
mov ax,OPEN_LINK ; check for empty list
mov bx,si
xchg bx,ems_front[bp]
cmp bx,ax
je sme1 ; if empty list

mov blk_forward[si],ax ; else link onto front of list
mov blk_backward[si],bx
mov blk_forward[bx],si
pop bx
ret

sme1: mov ems_back[bp],si ; create list with one element
mov blk_forward[si],ax
mov blk_backward[si],ax
pop bx
ret
set_mru_ems endp


;; set mru ram
;
; entry DS:SI most recently used table entry
; uses AX
;
set_mru_ram proc
push bx
mov ax,OPEN_LINK ; check for empty list
mov bx,si
xchg bx,ram_front[bp]
cmp bx,ax
je smr1 ; if empty list

mov blk_forward[si],ax ; else link onto front of list
mov blk_backward[si],bx
mov blk_forward[bx],si
pop bx
ret

smr1: mov ram_back[bp],si ; create list with one element
mov blk_forward[si],ax
mov blk_backward[si],ax
pop bx
ret
set_mru_ram endp


;; unlink ems list
;
; entry DS:SI block table entry
; uses AX
;
unlink_ems_list proc
cmp si,ems_back[bp]
je uel1 ; if EMS block is LRU

push bx
cmp si,ems_front[bp]
je uel2 ; if EMS block is MRU

mov ax,blk_forward[si] ; delete from middle of LRU list
mov bx,blk_backward[si]
mov blk_forward[bx],ax
xchg ax,bx
mov blk_backward[bx],ax
jmp uel3

uel1: jmp get_lru_ems

uel2: mov bx,blk_backward[si] ; delete from front of LRU list
mov blk_forward[bx],OPEN_LINK
mov ems_front[bp],bx

uel3: pop bx
ret
unlink_ems_list endp


;; unlink ram list
;
; entry DS:SI block table entry
; uses AX
;
unlink_ram_list proc
cmp si,ram_back[bp]
je url1 ; if RAM block is LRU

push bx
cmp si,ram_front[bp]
je url2 ; if RAM block is MRU

mov ax,blk_forward[si] ; delete from middle of LRU list
mov bx,blk_backward[si]
mov blk_forward[bx],ax
xchg ax,bx
mov blk_backward[bx],ax
jmp url3

url1: jmp get_lru_ram

url2: mov bx,blk_backward[si] ; delete from front of LRU list
mov blk_forward[bx],OPEN_LINK
mov ram_front[bp],bx

url3: pop bx
ret
unlink_ram_list endp

end


  3 Responses to “Category : Files from Magazines
Archive   : PJ91.ZIP
Filename : BLOCK.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/