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

 
Output of file : STREAM.ASM contained in archive : PJ91.ZIP
title stream i/o
include asm.inc

SIO_BUFSIZ equ 8192 ; stream io buffer size

stream_io_str struc
sio_position dd ? ; stream position
sio_offset dd ? ; buffer offset
sio_read_bc dw ? ; buffer byte count for reading
sio_write_bc dw ? ; buffer byte count for writing
sio_file_handle dw ? ; dos file handle
sio_buffer db SIO_BUFSIZ dup(?) ; stream buffer
stream_io_str ends


.data
ertx_disk_full db 'Disk full',0
ertx_fopen_mode db 'Bad mode in fopen',0
ertx_out_of_handles db 'Out of stream handles',0
ertx_stream_handle db 'Bad stream handle',0

.data?
stream_pointers dd FOPEN_MAX dup(?)


.code
extn free,ms_dos,ms_dos_strerror,set_strerror,malloc
public fclose,fopen,fread,fwrite


;; fclose
;
; entry BX stream handle
; exit Cf if error closing file or bad handle
; uses AX,BX
;
fclose proc
pushm di,si,es
call fwrite_flush ; write bytes left in stream buffer
jc fcl1 ; if disk full

call stream_struct_write ; access stream structure
jc fcl1 ; if bad handle

mov si,bx ; clear stream structure pointer
add si,si
add si,si
mov wptr stream_pointers[bp+si],NULL_POINTER
mov wptr stream_pointers[bp+si+2],NULL_POINTER

mov bx,es:sio_file_handle[di]
call free

mov ah,3Eh
call ms_dos_strerror

fcl1: popm es,si,di
ret
fclose endp


;; fopen
;
; entry AX mode, 'r' or 'w' to open for reading or writing
; DS:SI filename
; exit BX stream handle
; Cf if error
; uses AX
;
fopen proc
pushm cx,dx,di,es
cmp ax,'r'
mov dx,3D00h
je fop1 ; if opening file for reading only
cmp ax,'w'
jne fop3 ; if not open for write (unknown mode)
mov dh,3Ch
mov cx,0
fop1: mov ax,dx
mov dx,si
call ms_dos_strerror ; (ms dos with error handling)
jc fop2 ; if file open failed
mov dx,ax

call malloc_stream
jc fop4 ; if no memory or stream handles

mov al,0 ; zero stream structure (except for
mov cx,sio_buffer ; buffer space)
push di
rep stosb
pop di

mov es:sio_file_handle[di],dx
clc
fop2: popm es,di,dx,cx
ret

fop3: lea ax,ertx_fopen_mode ; *Bad mode in fopen*
call set_strerror
jmp fop2

fop4: mov ah,3Eh ; close file, no memory for structure
mov bx,dx
call ms_dos
stc
jmp fop2
fopen endp


;; fread
;
; entry BX stream handle
; CX byte count
; ES:DI destination pointer
; exit AX actual byte count (!=CX for EOF)
; DI updated
; Cf if error
;
fread proc
pushm di,bx,cx,dx,si,ds
cmp bx,stdin
je fre3 ; if special handle, standard input

call stream_struct_read
jc fre4
mov bx,si

fre1: jcxz fre4 ; if read finished

mov ax,wptr sio_position[bx]; compute stream position w/i buffer
mov dx,wptr sio_position[bx+2]
sub ax,wptr sio_offset[bx]
sbb dx,wptr sio_offset[bx+2]
jnz fre2 ; if buffer not w/i 64k of position

mov dx,sio_read_bc[bx] ; get number of bytes to end of buffer
sub dx,ax
jbe fre2 ; if stream position not in buffer

lea si,sio_buffer[bx]
add si,ax

call rep_movsb_limit

add wptr sio_position[bx],dx ; update stream position
adc wptr sio_position[bx+2],0
jmp fre1

fre2: call fread_primitive ; fill stream buffer
jbe fre4 ; if error (Cf==1) or EOF (Zf==1)
jmp fre1 ; else successful

fre3: mov ah,3Fh ; read from special handle stdin
mov dx,es
mov ds,dx
mov dx,di
call ms_dos_strerror
jc fre4

add di,ax ; (should not set Cf unless DI wraps)

fre4: popm ds,si,dx,cx,bx,ax
jc fre5 ; if error
neg ax ; else return bytes read
add ax,di
clc
fre5: ret
fread endp


;; fread primitive
;
; entry DS:BX stream structure
; exit AX bytes read from file
; Cf if error (Zf unknown)
; Zf if end of file
; uses SI
;
fread_primitive proc
pushm bx,cx,dx
mov si,bx

mov ax,4200h ; position file
mov bx,sio_file_handle[si]
mov dx,wptr sio_position[si]
mov cx,wptr sio_position[si+2]
call ms_dos_strerror
jc frp1 ; if error position file

mov wptr sio_offset[si],ax
mov wptr sio_offset[si+2],dx
mov sio_read_bc[si],0

mov ah,3Fh ; read file
mov cx,size sio_buffer
lea dx,sio_buffer[si]
call ms_dos_strerror
jc frp1 ; if read error
mov sio_read_bc[si],ax

or ax,ax ; set Zf for end of file
frp1: popm dx,cx,bx
ret
fread_primitive endp


;; fwrite
;
; entry BX stream handle
; CX byte count
; DS:SI source pointer
; exit AX bytes written
; SI updated
; Cf if error
;
fwrite proc
pushm si,cx,dx,di,es
cmp bx,stdout ; check for special streams
je fwr2 ; if writing to standard out
cmp bx,stderr
je fwr2 ; if writing to standard error

call fwrite_flush_maybe ; flush buffer in event of seek
jc fwr3 ; if bad handle or disk full

call stream_struct_write ; access stream structure
jc fwr3 ; if bad handle

fwr1: clc
jcxz fwr3 ; if write complete

mov ax,es:sio_write_bc[di] ; compute space left in stream buffer
mov dx,size sio_buffer
sub dx,ax
jb fwr3 ; if internal error (Cf=1)

push di ; copy to stream buffer
lea di,sio_buffer[di]
add di,ax
call rep_movsb_limit
pop di

add ax,dx ; update stream buffer byte count
mov es:sio_write_bc[di],ax ; and position
add wptr es:sio_position[di],dx
adc wptr es:sio_position[di+2],0

cmp ax,size sio_buffer ; check stream buffer level
jb fwr1 ; if not full
call fwrite_flush ; else write buffer to disk
jnc fwr1 ; if write successful
jmp fwr3 ; else disk full (Cf=1)

fwr2: mov ah,40h ; write standard output/error
mov dx,si
call ms_dos_strerror
jc fwr3 ; if write failed
add si,ax

fwr3: popm es,di,dx,cx,ax
jc fwr4 ; if error
neg ax ; else return bytes written
add ax,si
clc
fwr4: ret
fwrite endp


;; fwrite flush
;
; entry BX stream handle
; exit Cf if disk full, bad handle, or other error
; uses AX
;
fwrite_flush proc
pushm bx,cx,dx,si,ds
call stream_struct_read
jc fwf1 ; if bad handle

mov cx,sio_write_bc[si]
jcxz fwf1 ; if buffer empty (nothing to flush)

mov ax,4200h ; position file
mov bx,sio_file_handle[si]
mov dx,wptr sio_offset[si]
mov cx,wptr sio_offset[si+2]
call ms_dos_strerror
jc fwf1 ; if position failed

mov ah,40h ; write file
mov cx,sio_write_bc[si]
lea dx,sio_buffer[si]
call ms_dos_strerror
jc fwf1 ; if write failed

add wptr sio_offset[si],ax ; update buffer position
adc wptr sio_offset[si+2],0
mov sio_write_bc[si],0 ; clear output byte count

cmp ax,cx
je fwf1 ; if correct byte cnt written (Cf=0)

lea ax,ertx_disk_full ; else *Disk full*
call set_strerror

fwf1: popm ds,si,dx,cx,bx
ret
fwrite_flush endp


;; fwrite flush maybe
;
; entry BX stream handle
; exit Cf if bad handle or disk full
; uses AX,DX
;
fwrite_flush_maybe proc
pushm si,ds
call stream_struct_read
jc ffm2 ; if bad stream handle

mov ax,wptr sio_offset[si] ; compute buffer position
mov dx,wptr sio_offset[si+2]
add ax,sio_write_bc[si]
adc dx,0

cmp ax,wptr sio_position[si]
jne ffm1 ; if wrong position
cmp dx,wptr sio_position[si+2]
je ffm2 ; if right position

ffm1: call fwrite_flush
jc ffm2 ; if disk full

mov ax,wptr sio_position[si] ; reposition buffer
mov wptr sio_offset[si],ax
mov ax,wptr sio_position[si+2]
mov wptr sio_offset[si+2],ax

ffm2: popm ds,si
ret
fwrite_flush_maybe endp


;; malloc stream
;
; exit BX stream handle
; ES:DI stream structure
; Cf if no handles or memory left
; uses AX
;
malloc_stream proc
pushm cx,si
mov bx,stderr ; find free stream handle
mas1: inc bx
cmp bx,FOPEN_MAX
jae mas3 ; if no handles left

mov si,bx
add si,si
add si,si
les di,stream_pointers[bp+si]
mov ax,es
or ax,di
jnz mas1 ; if stream allocated

mov cx,size stream_io_str ; allocate memory for stream structure
call malloc
jc mas2 ; if no memory

mov wptr stream_pointers[bp+si],di
mov wptr stream_pointers[bp+si+2],es

mas2: popm si,cx
ret

mas3: lea ax,ertx_out_of_handles ; *Out of stream handles*
call set_strerror
jmp mas2
malloc_stream endp


;; rep movsb limit
;
; entry DS:SI source pointer
; ES:DI destination pointer
; CX byte count
; DX byte count limit
; exit SI,DI updated
; CX updated (nonzero if original DX ; DX actual number of bytes transfered (minimum of CX,DX)
;
rep_movsb_limit proc
push ax
cmp cx,dx ; DX is unsigned minimum of CX and DX
ja rmm1
mov dx,cx

rmm1: mov ax,cx ; this procedure implements a smart
sub ax,dx ; "rep movsb" instruction. the
mov cx,dx ; difference is it moves the minimum
rep movsb ; number of bytes specified in CX or
mov cx,ax ; DX. CX is updated normally; DX has
pop ax ; the actual number of bytes moved.
ret
rep_movsb_limit endp


;; stream struct read
;
; entry BX stream handle
; exit DS:SI stream structure
; Cf if bad handle
; uses AX
;
stream_struct_read proc
cmp bx,FOPEN_MAX
jae rss1 ; if handle too large
mov si,bx
add si,si
add si,si
lds si,stream_pointers[bp+si]
mov ax,ds
or ax,si
jz rss1 ; if inactive stream
ret

rss1: lea ax,ertx_stream_handle ; *Bad stream handle*
jmp set_strerror
stream_struct_read endp


;; stream struct write
;
; entry BX stream handle
; exit ES:DI stream structure
; Cf if bad handle
; uses AX
;
stream_struct_write proc
cmp bx,FOPEN_MAX
jae wss1 ; if handle too large
mov di,bx
add di,di
add di,di
les di,stream_pointers[bp+di]
mov ax,es
or ax,di
jz wss1 ; if inactive stream
ret

wss1: lea ax,ertx_stream_handle ; *Bad stream handle*
jmp set_strerror
stream_struct_write endp

end


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