Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP

Output of file : MINTFORM.ASM contained in archive : EMAC15ES.ZIP
;10-01-88 14:45:52 make get_mint_space return four numbers.
;12-06-87 00:51:14 finish adding 256K of mint space.
;12-06-87 00:26:46 start adding support for 256K of mint space.
;11-16-87 23:18:00 call new_buffer from init_forms.
page ,132

include mintform.def
include mint.def

comment /

The forms:

Forms are laid out as a linear list of forms. formStore points to the
beginning, and [topbot] points to the end. The most recently defined forms are
placed at the beginning of the list. The forms consists of three elements: a
header, the name, and the data. The header contains the link to the next
form, the length of the name, the length of the data, and the form pointer
(which is always <= the length of the data). The form structure is defined in
the file 'mintform.def'.
When a form is to be looked up in form storage, the form is first
hashed. Then the form is looked up in the list of hash links. A linear search
is performed for all the forms that hash to that value.

formhash is the hashing table for form names. It is a list of
pointers to forms. Each form, in turn, has a pointer to the next form
whose name hashes to the same entry in formhash. To add a new form, we
must add the name to the proper place in the table. To delete a form, the
form name must be removed from formhash. Their links in formhash and each
of the forms must be updated, then the remaining forms get moved up in

Also, whenever a form gets looked up, it is placed at the head of
the chain of hash pointers. The assumption is that it will be looked up
again shortly.


formSeg segment byte public

define_buffer form_

public syntax_table
syntax_table dw NIL
;don't put anything here.
formhashsize equ 256
formhash dw formhashsize dup(NIL)

formStore label byte

formSeg ends

segmoffs struc
offs dw ?
segm dw ?
segmoffs ends

data segment byte public

public syntax_seg
syntax_seg dw formSeg ;segment holding syntax table.

this_segment dw ? ;points to next formSegments to get.
this_form dd ? ;current form while enumerating.

public formSeg0, formSeg1, formSeg2, formSeg3
formSegments label word
formSeg0 dw ?
formSeg1 dw ?
formSeg2 dw ?
formSeg3 dw ?

extrn data_bottop: word

data ends

code segment byte public

assume cs:code

extrn buffer_free: near
extrn new_buffer: near
extrn put_number: near

public init_forms
mov cx,4
mov bx,offset formSegments
assume ds:data, es:data
push bx
push cx
mov cx,offset formStore
call new_buffer
pop cx
pop bx
jc init_forms_1
assume ds:data, es:formSeg
mov [bx],es ;remember this form segment.
add bx,2
push cx
mov di,offset syntax_table ;null out the hash table.
xor ax,ax
mov cx,256 + 1
rep stosw
mov ax,offset formStore ;->end of forms.
mov form_topbot,ax
mov form_bottop,ax
mov form_botbot,ax
pop cx
loop init_forms_0

public get_mint_space
;enter with di -> place to put numbers.
;return four numbers giving the bytes of mint space available,
; di ->end of strings.
mov dx,ds ;start with ds.
mov cx,4 ;do four segments.
push ds ;get the next segment
mov ds,dx
assume ds:formseg
mov dx,form_next_buffer
mov ds,dx
mov ax,form_bottop ;get the free space for this buffer.
sub ax,form_topbot
pop ds
assume ds:data

push dx
push cx
mov cx,0 ;use only as many digits as is needed.
mov bx,10
call put_number
mov al,',' ;seperate them by commas.
pop cx
pop dx
loop get_mint_space_1

;first_form sets us up to enumerate the forms (in no particular order).
; Returns es:bx ->next form, zr if there is no next form. Do not assume
; that es will remain the same from one call to the next.
public first_form, next_form
assume ds:data, es:data
mov this_segment,offset formSegments
assume ds:data, es:nothing
mov bx,this_segment
add this_segment,2 ;postincrement to the next seg.
cmp bx,offset formSegments + 4*2 ;last form segment?
jz next_last ;yes - we're done.
mov ax,[bx] ;get the formSegment.
mov this_form.segm,ax
mov this_form.offs,offset formStore ;->beginning of forms.
les bx,this_form
assume es:formSeg
mov ax,formSeg:[bx].form_length ;postincrement to the next form.
add this_form.offs,ax
cmp bx,form_topbot ;go if we have no more forms.
je next_segment

;enter with ds:bx -> a form. Make that form be the syntax table.

public store_syntax_table
assume ds:formSeg, es:data
mov syntax_table,bx
mov syntax_seg,ds

;define a form. Enter with:
; si => name
; cx = name length
; di => data
; dx = data length
; bx = form pointer.

public define_form
assume ds:data, es:data
push bx ;save the form pointer.
call find_form ;see if it already exists.
jc define_form_1 ;it doesn't.
assume es:formSeg
;check to see if the form is already big enough.
cmp dx,formSeg:[bx].data_length
ja define_form_3 ;it isn't.
pop formSeg:[bx].form_pointer ;set the form pointer.
mov si,di ;prepare to move the data.
lea di,formSeg:[bx].name_offset ;->name.
add di,cx ;->data.
mov formSeg:[bx].data_length,dx ;set the data length.
mov cx,dx ;copy the new data in.
rep movsb
assume es:formSeg
push di ;delete the form pointed to by es:bx
push si
push cx
call delete_form
pop cx
pop si
pop di
pop bx ;restore form pointer.
push di
push bx
push si
push cx
call hash_func ;exit with es:[bx]->hash entry.
assume es:formSeg
add cx,(size form_struc) ;compute amount of space needed.
add cx,dx
push cx ;push the size
mov ax,es
call buffer_free
jc define_form_2 ;go if we can't get enough mem.
mov di,form_topbot
pop formSeg:[di].form_length ;get the total size. (pushed as cx)
pop cx ;we have to pop into cx, because we
mov formSeg:[di].name_length,cx ; need it later for the movsb.
mov formSeg:[di].data_length,dx
pop si ;restore ->name
pop formSeg:[di].form_pointer
mov ax,formSeg:[bx] ;get current formhash
mov formSeg:[bx],di ;make formhash point to us.
mov formSeg:[di].hash_link,ax ;make us point to current formhash.
add di,name_offset ;lea di,[di].name_offset
rep movsb
pop si ;restore ->data
mov cx,dx
rep movsb
mov form_topbot,di ;remember the new end.
call nomem

;Find a form. Enter with:
; si -> name
; cx = name length
;Preserve di
;Exit with:
; nc if form found, es:bx -> form
; cy if form not found, es=data
public find_form
assume ds:data, es:data
push dx
push di
call hash_func
assume es:formSeg
push bx ;remember the formhash pointer.
xor dx,dx
mov bx,formSeg:[bx] ;get ->first form that hashes here.
cmp bx,NIL ;end of list?
je find_form_2 ;yes, we didn't find it.
cmp cx,formSeg:[bx].name_length ;lengths equal?
jne find_form_3 ;no, go to next.
lea di,formSeg:[bx].name_offset ;compare names.
push si
push cx
rep cmpsb
pop cx
pop si
jne find_form_3 ;names not equal.
pop di ;restore the formhash pointer.
or dx,dx ;did we find it first?
je find_form_4 ;yes - that's where we want it.
mov ax,formSeg:[di]
mov formSeg:[di],bx ;make head -> found.
xchg ax,formSeg:[bx].hash_link ;make found -> old head.
mov di,dx
mov formSeg:[di].hash_link,ax ;make pred(found) -> succ(found).
clc ;found the form!
pop di
pop dx
assume es:formSeg
mov dx,bx
mov bx,formSeg:[bx].hash_link
jmp find_form_1
pop bx ;restore the formhash pointer.
stc ;didn't find the form!
pop di
pop dx

;delete a form. Enter with:
; es:bx=>form

public delete_form
;delete the form from the hashing table.
assume ds:data, es:formSeg
mov di,bx ;make a copy of the pointer to the form.
mov cx,formSeg:[bx].name_length
lea si,formSeg:[bx].name_offset
assume ds:formSeg, es:data
call hash_func
assume es:formSeg
sub bx,hash_link ;pretend that formhash is a form itself.
cmp formSeg:[bx].hash_link,di ;does this form point to us?
je delete_form_2 ;yes.
mov bx,formSeg:[bx].hash_link ;no - go to the next form.
jmp delete_form_1
mov ax,formSeg:[di].hash_link ;unlink us from the list.
mov formSeg:[bx].hash_link,ax
;check for deletion of the syntax table.
cmp di,syntax_table
jne delete_form_7
mov syntax_table,NIL ;if we're deleting it, put NIL in.
;now adjust the hash links in formhash.
mov ax,formSeg:[di].form_length
mov bx,offset syntax_table
mov cx,formhashsize+1 ;add one for the syntax table.
cmp formSeg:[bx],di ;do we need to adjust this one?
jbe delete_form_4 ;no.
sub formSeg:[bx],ax ;yes - do it.
add bx,2
loop delete_form_3
;now adjust all the hash links in the forms. Notice that we are adjusting
; the hash link in the form we are about to delete, but it doesn't hurt.
; We can also presume the existence of at least one form at this point.
mov bx,offset formStore ;->beginning of forms.
cmp formSeg:[bx].hash_link,di ;do we need to adjust this one?
jbe delete_form_6 ;no.
sub formSeg:[bx].hash_link,ax ;yes - do it.
add bx,formSeg:[bx].form_length ;compute the form after this one.
cmp bx,form_topbot ;no forms after this one.
jb delete_form_5
mov si,di ;now move every form after this one down.
add si,ax
mov cx,form_topbot
sub cx,si
rep movsb
mov form_topbot,di ;remember the new form_topbot.

;find the form whose name is given in arg1. Return the form pointer in
;ds:si, and the number of bytes remaining in the form in cx.
public find_arg1
mov cx,1
;fall through to find_arg

;find the form whose name is given in the argument specified in cx. Return
; the form pointer in ds:si, and the number of bytes remaining in the form in
; cx, and the pointer to the form in bx.
public find_arg
assume ds:data, es:data
call getarg
call find_form
jc find_arg1_1 ;if form doesn't exist, exit.
assume ds:formSeg, es:data
lea si,formSeg:[bx].name_offset ;make si =>
add si,formSeg:[bx].name_length
add si,formSeg:[bx].form_pointer
mov cx,formSeg:[bx].data_length ;make cx = number of bytes left.
sub cx,formSeg:[bx].form_pointer
clc ;remember that form was found.

;enter with si,cx ->name to be hashed.
;exit with entry into hash table in ds:bx
;preserve dl.
assume ds:nothing
push si
push cx
xor bx,bx ;start with zero.
jcxz hash_func_1
xor ah,ah
add bx,ax
loop hash_func_2
mov al,bl ;save the low byte
mov bl,bh
mov bh,0
and bl,3 ;four segments = two bits.
add bx,bx ;we're accessing words.
mov es,formSegments[bx] ;get the correct segment.
mov bl,al ;get the low byte back. No need to
;zero bh again.
add bx,bx
add bx,offset formhash
pop cx
pop si

;Adjust the form pointer after building a value which affects the
; form pointer. The new form pointer is derived from the count
; of characters left in cx. The form is pointed to by bx.
public return_form
assume ds:formSeg, es:data
mov ax,formSeg:[bx].data_length
sub ax,cx
mov formSeg:[bx].form_pointer,ax
jmp return_tos

extrn return_tos: near
extrn getarg: near
extrn nomem: near
code ends


  3 Responses to “Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP

  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: