home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
edit
/
fremacsr
/
mintprim.asm
< prev
next >
Wrap
Assembly Source File
|
1987-02-15
|
28KB
|
1,254 lines
;History:1016,24
page ,132
.xlist
include mintdefs.asm
code segment byte public
code ends
data segment byte public
extrn next_ids: word
extrn formb: word
extrn forme: word
extrn fbgn: word
extrn fend: word
extrn actptr: word
extrn filename: byte
size_buf dw ?
public save_stack
save_stack dw ?
public read_errors
read_errors dw read_error_1
dw read_error_2
dw read_error_3
dw read_error_4
dw read_error_5
public write_errors
write_errors dw write_error_1
dw write_error_2
dw write_error_3
dw write_error_4
read_error_1 label byte
read_error_2 db 'File too large'
read_error_3 db 'File not found'
read_error_4 db 'End of file'
read_error_5 label byte
write_error_1 label byte
write_error_2 db 'Disk full'
write_error_3 db 'Directory full or bad filename'
write_error_4 label byte
environ_name db 'env.'
environ_name_len equ $-environ_name
db 'RUNLINE'
runline_len equ $-environ_name
switchar_name db 'env.SWITCHAR'
switchar_len equ $-switchar_name
form_prefix_len dw ? ;for use by ln prim
form_prefix_ptr dw ? ;...
out_of_memory_msg db 'Not enough memory.$'
break_state db ? ;=state of break checking flag.
extrn stackp: byte
public phd_seg
phd_seg dw ?
data ends
code segment byte public
assume cs:code, ds:data, es:data
;starting address of program.
init:
mov ax,data
mov ds,ax
mov phd_seg,es
mov es,ax
cli
mov ss,ax
mov sp,offset stackp
sti
push ds
mov ds,phd_seg
mov bx,ds:[2]
pop ds
mov dx,bx
sub dx,ax ;compute memory between data and end.
cmp dx,1000h ;more than 64k?
jb init_exit ;no - not enough memory.
add ax,1000h ;start buffers at the next segment up.
call mint_init
jc init_exit ;no memory.
call init_entry
call init_screen
call pick_init
call paint_screen
mov ax,0ffffh ;start at the end of memory.
mov formb,ax ;delete all forms.
mov forme,ax
push ds ;set the fatal error address.
push cs
pop ds
mov dx,offset abort_fatal
mov ax,2524h
int 21h
pop ds
mov ax,33h*256+0 ;get the break state.
int 21h
mov break_state,dl
mov ax,33h*256+1 ;turn break checking off.
mov dl,0
int 21h
jmp init_ids
init_exit:
mov dx,offset out_of_memory_msg
mov ah,9
int 21h
mov ax,4c01h
int 21h ;halt because of no memory.
extrn lastcode: byte
extrn init_screen: near
extrn pick_init: near
extrn init_ids: near ;restart mint interpreter
extrn abort_fatal: near ;fatal error handler
extrn mint_init: near ;perform any special mint initing.
extrn return_null: near
extrn paint_screen: near ;start with the screen unpainted.
;The following two externs init and uninit anything that's machine specific.
extrn init_entry: near
extrn uninit_exit: near
extrn set_form_pointer: near
;set_form_pointer updates the form pointer. It does the dirty work
; for return_form.
extrn return_form: near
;return_form updates the form pointer and jumps to return_tos
extrn return_arg: near
extrn return_arg_active: near
;return_arg and return_arg_active return the argument whose number is given
; in cx. return_arg_active always returns the argument as active.
extrn return_string: near
;return_string returns the ALth string out of the table pointed to by bx.
extrn return_sicx: near
;return_sicx returns the string pointed to by si. The length of the
; string is given in cx.
extrn return_tos: near
;return_tos returns the string pointed to by the top of the stack.
; The length of the string is the difference between di and the
; beginning of the stirng.
extrn nomem: near
;primitives here
hl_prim:
call get_decimal_arg1 ;get the return code.
push ax
mov ax,33h*256+1 ;set the break state.
mov dl,break_state
int 21h
call uninit_exit
pop ax
mov ah,4ch
int 21h
eq_prim:
call getarg1 ;get the first argument
mov dx,cx ;save size of first argument
mov di,si ;save pointer to first argument
mov cx,2 ;get second argument
call getarg
cmp cx,dx ;lengths equal?
jne eq_prim_1 ;no, return 4th
repe cmpsb ;strings equal?
jne eq_prim_1 ;no, return 4th.
mov cx,3
jmp return_arg
eq_prim_1:
mov cx,4
jmp return_arg
nc_prim:
call getarg1
di_points_fbgn
mov ax,cx
jmp return_number
sc_prim:
bc_prim:
mov cx,2 ;get 'from' argument.
call getarg
mov dl,'a' ;default to ASCII
jcxz bc_prim_1
mov dl,[si] ;get from type.
bc_prim_1:
mov cx,3 ;get 'to' argument.
call getarg
mov dh,'d' ;default to decimal
jcxz bc_prim_2
mov dh,[si]
bc_prim_2:
call getarg1
call bc_prim_base ;get the source base.
or bx,bx ;ASCII?
jnz bc_prim_4 ;no.
lodsb
mov ah,0
jmp bc_prim_3
bc_prim_4:
push dx ;preserve dx.
call get_number
pop dx
bc_prim_3:
;we now have the number in ax.
mov dl,dh
call bc_prim_base
di_points_fbgn
or bx,bx
jnz bc_prim_5
stosb
jmp return_tos
bc_prim_5:
mov cx,0 ;use only as many digits as are needed.
call put_number
jmp return_tos
;private subroutine, used only bc_prim.
bc_prim_base:
;enter with dl=base character.
;exit with bx=base if number; bx=0 if ASCII.
or dl,20h ;convert UPPER case to lower case.
cmp dl,'d'
jne bc_prim_base_1
mov bx,10
ret
bc_prim_base_1:
cmp dl,'o'
jne bc_prim_base_2
mov bx,8
ret
bc_prim_base_2:
cmp dl,'h'
jne bc_prim_base_3
mov bx,16
ret
bc_prim_base_3:
cmp dl,'c'
jne bc_prim_base_4
mov bx,0
ret
bc_prim_base_4:
cmp dl,'a' ;a alias character.
jne bc_prim_base_5
mov bx,0
ret
bc_prim_base_5:
cmp dl,'b'
jne bc_prim_base_6
mov bx,2
ret
bc_prim_base_6:
ret
db_prim:
int 3
jmp return_null
dt_prim:
di_points_fbgn
mov ah,2ah
int 21h
mov bx,10 ;do all conversions in decimal.
push cx
push dx
mov al,dh ;get month
mov ah,0
mov cx,2
call put_number
mov al,"-"
stosb
pop ax ;pushed as dx (get date)
mov ah,0
mov cx,2
call put_number
mov al,"-"
stosb
pop ax ;pushed as cx (get year)
sub ax,1900 ;only output the last two digits.
mov cx,2
call put_number
jmp return_tos
tm_prim:
di_points_fbgn
mov ah,2ch
int 21h
mov bx,10 ;do all conversions in decimal.
push dx
push cx
mov al,ch ;get hours
mov ah,0
mov cx,2
call put_number
mov al,":"
stosb
pop ax ;pushed as cx (get minutes)
mov ah,0
mov cx,2
call put_number
mov al,":"
stosb
pop dx ;get seconds
mov al,dh
mov ah,0
mov cx,2
call put_number
jmp return_tos
;form primitives
ds_prim:
mov cx,2 ;get data first.
call getarg
mov dx,cx
mov di,si
call getarg1
mov bx,0 ;reset form pointer.
call define_form
jmp return_null
ss_prim:
call find_arg1
jnc ss_prim_3
mov dx,[bx].data_length ;save the count of the form in dx.
lea di,[bx].name_offset
add di,[bx].name_length ;save the pointer to the form in di.
mov si,fbgn ;point si at the zeroth arg.
mov si,[si] ;point si at the form name.
mov si,[si] ;point si at the first argument.
mov ah,sgap+1 ;start with sgap 1.
ss_prim_1:
cmp si,[si] ;are we pointing at fend?
je ss_prim_3
push si ;save pointer to args.
mov cx,[si] ;compute length of this arg.
sub cx,si
sub cx,mark_overhead
add si,mark_overhead-1 ;make si=> text of argument.
;at this point, si,cx => arg; di,dx => form.
push di
push dx
jcxz ss_prim_5 ;ignore null strings.
ss_prim_4:
call string_search
jc ss_prim_5 ;not found. Done with this arg.
;at this point, we have found a string. We proceed to replace it by
;the appropriate segment gap. We have already ensured that the string
;is at least one character long.
push cx ;preserve cx
mov al,ah ;get the sgap.
stosb ;store it.
;by the way, at this point, the relation (cx <= dx) is always true.
sub dx,cx ;count it, and the ones we're getting rid of.
dec cx ;one less to get rid of.
mov al,sgap ;get rid of the rest of the chars.
rep stosb ;cx may be zero, but it doesn't hurt.
pop cx
jmp ss_prim_4
ss_prim_5:
pop dx
pop di
pop si ;restore pointer to args.
mov si,[si] ;make it point to next arg.
inc ah ;increment sgap to next arg.
jmp ss_prim_1
ss_prim_3:
jmp return_null
nb_prim:
call find_arg1
mov cx,3
jnc nb_prim_1
mov cx,2
nb_prim_1:
jmp return_arg
;default primitive is the same as the cl primitive, only we start counting
; arguments from zero, not one.
dflt:
mov bp,0
jmp cl_prim_entry
cl_prim:
mov bp,1
cl_prim_entry:
mov cx,bp ;get the number of the form name arg.
di_points_fend
call find_arg
jnc cl_prim_1
jcxz cl_prim_1 ;if no characters, return null.
or bp,bp ;is this dflt or cl?
jne cl_prim_2 ;cl - use specified args.
dec bp ;make bp+1 be the number of the form name arg.
cl_prim_2:
lodsb ;get char
or al,al ;test it for sgapness
jge cl_prim_3 ;go if not sgap
sub al,sgap ;which sgap?
jz cl_prim_4 ;ignore sgap0's
cbw ;we're going to be counting off ax
add ax,bp ;add in the first arg number.
push si ;preserve pointer, count of the form
push cx
mov cx,ax
call getarg
chk_actptr_cnt
rep movsb
pop cx ;restore pointer, count of the form
pop si
jmp cl_prim_4
cl_prim_3:
chk_actptr
stosb
cl_prim_4:
loop cl_prim_2
cl_prim_1:
jmp return_tos
cc_prim:
call find_arg1
jnc cc_prim_1 ;form not found.
jcxz cc_prim_2 ;no chars left.
di_points_fbgn
movsb ;no need to check for collision with actptr.
dec cx
jmp return_form
cc_prim_2:
mov cx,2
jmp return_arg_active
cc_prim_1:
jmp return_null
cr_prim:
call find_arg1
jnc cr_prim_1
mov [bx].form_pointer,0
cr_prim_1:
jmp return_null
cn_prim:
call find_arg1
jnc cn_prim_1
jcxz cn_prim_2
push si ;save pointer, count to form.
push cx
push bx
mov cx,2 ;get number of chars to call.
call get_decimal_arg
mov dx,ax ;save in dx.
pop bx
pop cx
pop si
di_points_fbgn
cmp dx,cx ;are we trying to get more than exists?
jbe cn_prim_3 ;no - move the requested amount.
mov dx,cx ;yes - truncate to the amount that exists.
cn_prim_3:
xchg dx,cx ;swap the count remaining and the get count.
sub dx,cx ;dec the count remaining by the get count.
chk_actptr_cnt ;check for collision
rep movsb ;move all the chars.
mov cx,dx ;return the count remaining in cx.
jmp return_form
cn_prim_2:
mov cx,3
jmp return_arg_active
cn_prim_1:
jmp return_null
in_prim:
call find_arg1
jnc in_prim_1 ;if form not found, return null.
jcxz in_prim_2 ;if nothing to search, return two.
push si
mov di,si
mov dx,cx
mov cx,2
call getarg
;now si,cx => short string, di,dx => long string.
call string_search
jc in_prim_3 ;if it's not found, just return arg 3.
;what we want to do now is to return the string from [tos] to [di],
; and advance the form pointer to point after the found string.
sub dx,cx ;dx gets long length - short length.
pop si
mov cx,di ;get the number of characters before
sub cx,si ; the search string.
di_points_fbgn ;prepare to return a string.
chk_actptr_cnt ;make sure we have enough room.
rep movsb
mov cx,dx ;return_form expects the count in cx.
jmp return_form
in_prim_3:
add sp,2 ;get rid of the pointer to the search string.
in_prim_2:
mov cx,3
jmp return_arg_active
in_prim_1:
jmp return_null
ev_prim:
xor si,si ;start at the beginning of the environ.
ev_prim_1:
mov di,fbgn
push si ;copy in the environ name.
mov si,offset environ_name
mov cx,environ_name_len
rep movsb
pop si
push ds
mov ds,phd_seg
mov ds,ds:[2ch]
mov cx,environ_name_len ;start with what we've got already.
ev_prim_2:
inc cx
lodsb
stosb
or al,al
jne ev_prim_2
pop ds
dec cx ;don't count the null.
cmp cx,environ_name_len ;did we get any at all?
je ev_prim_3 ;if none, we're done.
push si ;remember the environment pointer.
mov di,fbgn ;make di->entire name.
mov si,di ;make si -> the name.
mov al,'=' ;look for the name/data separator.
repne scasb
mov dx,cx ;dx (data length) is number of chars left.
mov cx,di ;compute the name length.
sub cx,si
dec cx ;don't count the '='.
;define a form. Enter with:
; si => name
; cx = name length
; di => data
; dx = data length
; bx = form pointer.
xor bx,bx
call define_form
pop si
jmp ev_prim_1
ev_prim_3:
mov di,fbgn
mov si,80h
push ds
mov ds,phd_seg
lodsb ;get the line length.
mov dl,al
mov dh,0
mov cx,dx ;put it where movs can destroy it.
rep movsb
pop ds
mov di,fbgn ;restore di again.
mov si,offset environ_name
mov cx,offset runline_len
xor bx,bx
call define_form
mov ax,3700h ;get the switchar.
int 21h
mov di,fbgn
mov [di],dl ;store the switchar.
mov dx,1 ;set the data length.
mov si,offset switchar_name
mov cx,offset switchar_len
xor bx,bx
call define_form
jmp return_null
if 0
pa_prim:
;#(ps,prefix, seperator, arguments)
di_points_fend
call getarg1 ;get seperator and save it.
mov bp,si ;store the pointer to arg1 in bp
mov dx,cx ;store the size of arg1 in dx
mov cx,2 ;get the form prefix.
call getarg
mov form_prefix_len,cx
mov form_prefix_ptr,si
mov si,fbgn ;point si at the zeroth arg.
mov si,[si] ;point si at the prefix
mov si,[si] ;point si at the seperator.
mov si,[si] ;point si at the arguments.
pa_prim_1:
cmp si,[si] ;are we pointing at fend?
je pa_prim_2 ;yes, exit.
push si ;save pointer to args.
mov cx,[si] ;compute length of this arg.
sub cx,si
sub cx,mark_overhead
add si,mark_overhead-1 ;make si=> text of argument.
;at this point, si,cx => arg
cmp cx,dx ;is argument length < prefix length?
jb pa_prim_4 ;yes - prefix can't match.
push di ;save the source pointers.
push si
push cx
mov di,bp
mov cx,dx
repe cmpsb ;compare the prefix to the form name.
pop cx
pop si
pop di
jne pa_prim_4 ;the prefixes didn't match - ignore it.
pa_prim_3:
chk_actptr_cnt
rep movsb ;move the name in.
mov si,form_prefix_ptr ;get the seperator ptr, count.
mov cx,form_prefix_len
chk_actptr_cnt
rep movsb ;move it in.
pa_prim_4:
pop si ;get the argument pointer back.
mov si,[si] ;get the next argument.
jmp pa_prim_1 ;and continue.
pa_prim_2:
jmp return_tos
endif
ln_prim:
mov bx,formb ;get pointer to forms.
di_points_fend
call getarg1 ;get seperator and save it.
mov bp,si ;store the pointer to arg1 in bp
mov dx,cx ;store the size of arg1 in dx
mov cx,2 ;get the form prefix.
call getarg
mov form_prefix_len,cx
mov form_prefix_ptr,si
ln_prim_1:
cmp bx,forme ;at end?
je ln_prim_2 ;yes, exit.
lea si,[bx].name_offset ;get the name pointer.
mov cx,form_prefix_len
jcxz ln_prim_3 ;zero prefixes match anything.
cmp cx,[bx].name_length ;is prefix length>name length?
ja ln_prim_4 ;yes - prefix can't match.
push di ;save the source pointers.
push si
mov di,form_prefix_ptr
repe cmpsb ;compare the prefix to the form name.
pop si
pop di
jne ln_prim_4 ;the prefixes didn't match - ignore it.
ln_prim_3:
mov cx,[bx].name_length ;get the name length
chk_actptr_cnt
rep movsb ;move the name in.
mov si,bp ;get the pointer to arg1.
mov cx,dx ;get the size of arg1.
chk_actptr_cnt
rep movsb ;move it in.
ln_prim_4:
add bx,[bx].form_length ;point to next form.
jmp ln_prim_1 ;and continue.
ln_prim_2:
jmp return_tos
dd_prim:
mov si,fbgn ;point si at "dd".
mov si,[si] ;point si at the first arg.
dd_prim_1:
cmp si,[si] ;are we pointing at fend?
je dd_prim_3
push si ;save pointer to args.
mov cx,[si] ;compute length of this arg.
sub cx,si
sub cx,mark_overhead
add si,mark_overhead-1 ;make si=> text of argument.
call find_form ;try to find this form.
jnc dd_prim_2 ;go if it didn't exist.
call delete_form ;delete the form if it did exist.
dd_prim_2:
pop si ;restore pointer to args.
mov si,[si] ;make it point to next arg.
jmp dd_prim_1
dd_prim_3:
jmp return_null
sb_prim:
call getarg1_filename
mov dx,si
mov cx,0
mov ah,3ch ;create file.
int 21h
mov bx,ax ;remember the handle.
mov al,2
jc sb_prim_4
mov si,fbgn ;point si at the zeroth arg.
mov si,[si] ;point si at the form name.
mov si,[si] ;point si at the first search string.
sb_prim_1:
cmp si,[si] ;are we pointing at fend?
je sb_prim_3
push si ;save pointer to args.
mov cx,[si] ;compute length of this arg.
sub cx,si
sub cx,mark_overhead
add si,mark_overhead-1 ;make si=> text of argument.
push bx
call find_form
mov di,bx ;remember where the form is.
pop bx
jnc sb_prim_2 ;go if it isn't there.
mov cx,[di].form_length
mov dx,di
mov ah,40h ;write to a file
int 21h
jnc sb_prim_2 ;no problem.
mov ah,3eh ;disk full - close the file.
int 21h
mov dx,offset filename ;delete the file.
mov ah,41h
int 21h
mov al,1
jmp short sb_prim_4
sb_prim_2:
pop si ;restore pointer to args.
mov si,[si] ;make it point to next arg.
jmp sb_prim_1
sb_prim_3:
mov ah,3eh ;close the file.
int 21h
mov al,0 ;no problem.
sb_prim_4:
mov bx,offset write_errors
jmp return_string
fb_prim:
;Note that information about the structure 'form' is hard-coded into the
; next routine. We assume that 'form_length' is only two bytes long,
; and occurs at the beginning of the structure.
call getarg1_filename
mov dx,si
mov ax,3d00h ;open file for reading.
int 21h
mov bx,ax ;remember the handle.
mov al,2
jc fb_prim_4_j_1
mov ax,forme ;anything loaded yet?
cmp ax,formb
jne fb_prim_1 ;yes - load one by one.
mov cx,0
mov dx,cx
mov ax,4202h ;seek to the end of the file.
int 21h
push ax ;remember the file size.
mov dx,cx ;zero out dx again.
mov ax,4200h
int 21h
pop cx ;get the file size back again.
mov ax,forme ;no - do a bulk load.
sub ax,cx ;see if there is enough room.
jb fb_prim_3_j ;can't possibly be.
mov dx,ax
sub ax,free_space ;free_space is the working room.
cmp ax,fend
jb fb_prim_3_j ;there isn't.
mov cx,formb ;compute size of active string.
sub cx,actptr
mov si,actptr ;->active string.
mov di,dx ;->new formb.
sub di,cx ;leave room for the active string.
mov actptr,di
rep movsb
mov formb,dx
mov cx,-1 ;read the whole file in.
mov ah,3fh ;read from a file.
int 21h
jc fb_prim_5 ;trouble reading...
push bx ;preserve handle.
call rehash ;reconstruct the hash links.
pop bx
fb_prim_6:
mov ah,3eh ;close the file.
int 21h
mov al,0 ;all ok.
jmp fb_prim_4 ;we destroyed the active string.
fb_prim_5:
mov ah,3eh ;close the file.
int 21h
mov al,3 ;read error.
fb_prim_4_j_1:
;we get here if we can't open the file.
jmp fb_prim_4 ;we destroyed the active string.
fb_prim_3_j:
jmp fb_prim_3
fb_prim_1:
mov dx,offset size_buf ;set disk transfer address
mov cx,2
mov ah,3fh ;read from a file.
int 21h
jc fb_prim_5 ;close the file - trouble reading.
cmp ax,0 ;did we read no bytes at all?
je fb_prim_6 ;close and exit.
mov ax,size_buf ;we need twice as much memory
shl ax,1 ; as in size_buf.
add ax,fend ;see if there is enough room.
add ax,free_space
cmp ax,actptr
jae fb_prim_3
mov dx,fend
add dx,2
mov cx,size_buf
sub cx,2 ;transfer two less bytes.
mov ah,3fh ;read from a file.
int 21h
jc fb_prim_5
cmp ax,cx
jne fb_prim_5 ;trouble reading...
push bx
mov bx,fend ;don't add 2 like we did before because
mov cx,[bx].name_length ; we already read form_length.
mov dx,[bx].data_length
lea si,[bx].name_offset
mov di,si
add di,cx ;or [bx].name_length, but cx is cheaper.
mov bx,[bx].form_pointer
call define_form
pop bx
jmp fb_prim_1
fb_prim_3:
mov ah,3eh ;close the file.
int 21h
jmp nomem
fb_prim_4:
mov bx,offset read_errors
jmp return_string
ad_prim:
call get_math
add ax,bx
push si
jmp return_number
su_prim:
call get_math
sub ax,bx
push si
jmp return_number
ml_prim:
call get_math
imul bx
push si
jmp return_number
dv_prim:
call get_math
or bx,bx
je dv_prim_1
cwd
idiv bx
dv_prim_1:
push si
jmp return_number
md_prim:
call get_math
or bx,bx
je md_prim_1
cwd
idiv bx
mov ax,dx
md_prim_1:
push si
jmp return_number
gr_prim:
call get_math
mov cx,3
cmp ax,bx
jg gr_prim_1
mov cx,4
gr_prim_1:
jmp return_arg
;primitive externals
public dflt
public hl_prim
public eq_prim
public nc_prim
public sc_prim
public db_prim
public dt_prim
public tm_prim
;forms
public ds_prim
public ss_prim
public cl_prim
public cc_prim
public cn_prim
public cr_prim
public in_prim
public ev_prim
public ln_prim
public dd_prim
public sb_prim
public fb_prim
public nb_prim
;math
public ad_prim
public su_prim
public ml_prim
public dv_prim
public md_prim
public gr_prim
;form subroutines
extrn define_form: near
extrn delete_form: near
;delete_form deletes the form pointed to by bx.
extrn rehash: near
;rehash rebuilds the hashing links. Used only when a file is bulk loaded.
extrn find_form: near
;find_form returns bx pointing to the form whose name is pointed to by si.
; The length of the form name is given in cx.
; If the form doesn't exist, cy is set, otherwise cy is clear.
; di points to the form data after the form pointer, and cx is the
; number of chars after the form pointer.
extrn find_arg1: near
;find_arg1 returns bx pointing to the form whose name is given in
; arg1. If the form doesn't exist, cy is set, otherwise cy is clear.
; di points to the form data after the form pointer, and cx is the
; number of chars after the form pointer.
extrn find_arg: near
;find_arg returns bx pointing to the form whose name is given in
; the arg specified by cx. If the form doesn't exist, cy is
; set, otherwise cy is clear. di points to the form data
; after the form pointer, and cx is the number of chars after
; the form pointer.
;utility subroutines
public get_math
get_math:
;exit with ax=first number, bx=second number, si->first arg, di->first number.
mov cx,2
call get_decimal_arg
push ax
call getarg1
push si
call get_decimal
mov di,si
pop si
pop bx ;pushed as ax
ret
public get_decimal_arg1
get_decimal_arg1:
mov cx,1
;fall through
public get_decimal_arg
get_decimal_arg:
call getarg
;fall through
public get_decimal
get_decimal:
mov bx,10
;fall through
public get_number
get_number:
;enter with si,cx => string containing trailing number, bx=base to convert
; number in. Return number in ax, si => start of digit string.
add si,cx
push cx
get_number_1:
dec si
mov al,[si]
sub al,"0" ;between 0 and "9"?
jb get_number_2 ;no - can't be a digit.
cmp al,"9"-"0" ;between "0" and "9"?
jbe get_number_6 ;yes - must be a digit.
cmp al,"a"-"0"
jb get_number_8
sub al,"a"-"A"
get_number_8:
cmp al,"A"-"0" ;between "A" and "9"?
jb get_number_2 ;yes - can't be a digit.
sub al,"A"-("0"+10) ;convert "A" to 10
get_number_6:
cmp al,bl ;a legal digit in the desired base?
jae get_number_2 ;no.
loop get_number_1
dec si ;setup for pre-increment.
get_number_2:
mov dx,cx
pop cx ;restore count.
sub cx,dx ;get the actual count of chars into cx.
inc si
push si ;save a copy of the start of the number.
mov ax,0 ;initially zero.
;at this point, si => first digit, cx = count of digits to convert.
jcxz get_number_4 ;if no more chars, we're done.
get_number_3:
mul bx
mov dx,ax
lodsb ;ax = new ASCII digit.
sub al,"0" ;make it a number.
cmp al,"9"-"0"
jbe get_number_7
cmp al,"a"-"0"
jb get_number_9
sub al,"a"-"A"
get_number_9:
sub al,"A"-("0"+10)
get_number_7:
cbw ;make it a word.
add ax,dx ;and add in the old value.
loop get_number_3
get_number_4:
pop si
cmp byte ptr -1[si],"-"
jne get_number_5
dec si
neg ax
get_number_5:
ret
public return_number
return_number:
;enter with di => place to put string, tos => start of string,
; ax=number.
mov cx,0 ;use only as many digits as is needed.
mov bx,10
call put_number
jmp return_tos
public put_number
put_number:
;enter with di => place to put string, ax = number, cx=minimum number of digits
; bx=base to convert number to.
or ax,ax
jge put_number_1
neg ax
mov byte ptr [di],"-"
inc di
put_number_1:
call one_digit
ret
one_digit:
jcxz one_digit_3
dec cx
one_digit_3:
cwd
div bx
push dx
or ax,ax
jnz one_digit_1 ;if more digits, do them.
jcxz one_digit_2 ;if count is zero, don't do next digit.
;we get here if we have more digits to do, or we have more leading
; zeroes to place.
one_digit_1:
call one_digit
one_digit_2:
pop ax ;pushed as dx
add al,"0"
cmp al,"9"
jbe one_digit_4
add al,"A"-("9"+1) ;the digit above "9" becomes an "A".
one_digit_4:
chk_actptr
stosb
ret
string_search:
if 1
;enter with si,cx => short string, di,dx => long string.
;exit with nc if string was found, di,dx => position found.
;exit with cy if string was not found.
jcxz string_search_3 ;zero length strings are found immediately
;we can get into trouble if cx = 0 after this point.
string_search_1:
cmp dx,cx
jb string_search_2
push si ;preserve all the registers.
push di
push cx
repe cmpsb
pop cx
pop di
pop si
je string_search_3
dec dx
inc di
jmp string_search_1
string_search_3:
clc
ret
string_search_2:
stc
ret
else
;enter with si,cx => short string, di,dx => long string.
;exit with nc if string was found, di,dx => position found.
;exit with cy if string was not found.
;preserve si,cx, ah.
jcxz string_search_1 ;zero length strings are found immediately
mov bx,cx ;save search string length.
mov cx,dx ;get target string length.
mov dx,si ;save search string pointer.
dec bx
sub cx,bx ;this many fewer chars to look at.
jb string_search_5 ;string is shorter than search.
string_search_3:
jcxz string_search_5 ;no chars to look at.
mov si,dx
lodsb ;get the first char.
string_search_4:
scasb ;look for the first char.
loopnz string_search_4 ;keep looking until we find it.
jnz string_search_5 ;we didn't
xchg cx,bx ;set the count to the string length.
push cx ;save the string length
push di ;save the source position
repe cmpsb ;is this it?
mov cx,bx ;restore the search length
pop di ;restore the source position
pop bx ;restore the string length
jne string_search_3 ;no match - try at next position.
mov si,dx ;restore search pointer
dec di ;make di point to the first char again.
mov dx,cx ;return the remaining count in dx.
mov cx,bx ;restore search count
inc cx ;restore count's original value.
string_search_1:
clc
jmp short string_search_2
string_search_5:
stc
string_search_2:
ret
endif
public getarg1_filename
getarg1_filename:
mov cx,1
public getarg_filename
getarg_filename:
call getarg
mov di,offset filename
rep movsb
xor al,al
stosb
mov si,offset filename
ret
extrn getarg1: near
;getarg1 returns si -> the first argument. cx is set to the size
; of the first argument.
extrn getarg: near
;getarg returns si -> the argument given in cx. cx is set to the size
; of the argument.
code ends
end init