home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
sigm
/
vol247
/
examples.lbr
/
PS.AQ6
/
ps.a86
Wrap
Text File
|
1986-02-27
|
12KB
|
338 lines
;
; miscellaneous equates...
zero equ 0
one equ 1
cr equ 0dh
lf equ 0ah
; set up code segment group
codeseg cseg
cgroup group codeseg
; first initialize the UDA field of all of the sub-process process
; descriptors. The UDA field must contain the offset in number of
; paragraphs from the beginning of the data segment where each of
; the sub-process UDA's reside.
; initialize processor descriptor uda field for sub-process 0
mov ax,offset uda0
mov cl,4
shr ax,cl ; compute number of paragraphs's
mov pd0_uda,ax
; initialize processor descriptor uda field for sub-process 1
mov ax,offset uda1
mov cl,4
shr ax,cl ; compute number of paragraphs's
mov pd1_uda,ax
; initialize processor descriptor uda field for sub-process 2
mov ax,offset uda2
mov cl,4
shr ax,cl ; compute number of paragraphs's
mov pd2_uda,ax
; initialize processor descriptor uda field for sub-process 3
mov ax,offset uda3
mov cl,4
shr ax,cl ; compute number of paragraphs's
mov pd3_uda,ax
; Create initial seed for random number generator. We'll use the seconds
; field of the system time of day.
mov dx,offset time_of_day
call t_seconds ; get the time of day
mov ax,min_sec ; get seconds
mov r,ax ; store seed.
; Create the sub processes, since the link fields point from sub-process 0
; to sub-process 1 on up to sub-process 3, only one process create call
; is needed. See the CCP/M Programmer's Guide for more information on the
; process descriptor fields,
mov dx,offset pd0
call p_create
; signon and set up the screen.
mov dx,offset signon
call c_writestr
; Everything is now set up, so loop printing the status of the sub-processes
; until a character is typed.
print_status:
mov dx,offset status_mess ; print the status message
call c_writestr
mov dl,0ffh ; character status code
call c_rawio ; character typed ?
cmp al,0
jz print_status ; nope, continue looping
; Character has been typed, so set the abort flag so the sub-processes will
; also abort, and print the exit message
mov abort,1 ; set abort flag
mov dx,offset exit_mess
call c_writestr ; print the exit message
call p_termcpm ; abort the main program
; The following is the code for each of the sub-processes. The sub-process
; number has already been placed in the BX register of each of the
; sub-processes. This value will be used as a seed for the random number
; generator and as an index into the process status table
sub_proc:
call delay ; delay for a random period of time
call toggle ; toggle the processes status
call check ; check the abort flag
jmp sub_proc ; do this forever
; Delay for some period of time.
delay:
; First compute a random number, I'm using the same algorithm that is used in
; the Cbasic compiler.
push bx ; save device number
mov ax,12949 ; knuth multiplier
mul r ; get the seed
add ax,6925 ; knuth constant
and ah,7fh ; make it 15 bit value
cwd ; ensure high 16 bits off before devide
mov r,ax ; save new random number to use as seed
; for next call.
mov si,328 ; scale it from 0-99
div si
; We've got a random number between 0 and 99, so let's delay that number of
; ticks.
mov dx,ax ; set up number of ticks for delay call
call p_delay ; pause for some period of time
pop bx ; restore device number.
ret
; toggle the current status for the device from '0' to '1' or vise-versa
toggle: push bx ; save sub-process number
mov al,4
mul bl ; compute offset
mov bx,ax
mov al,status[bx] ; get current status
cmp al,48 ; is it zero ?
jz is_one ; yep, change it to one
is_zero:
mov al,48 ; nope, change it to zero
jmp update_status
is_one: mov al,49
update_status:
mov status[bx],al ; update status table
pop bx ; restore sub-process number
ret
; should we abort ???
check:
cmp abort,0 ; is it zero
jnz exit ; nope, abort the program
ret ; otherwise just return
exit: call p_termcpm
;
; Concurrent CP/M System calls
;
c_assign: mov cl,149 ! jmp call_cpm
c_attach: mov cl,146 ! jmp call_cpm
c_detach: mov cl,147 ! jmp call_cpm
c_read: mov cl,1 ! jmp call_cpm
c_readstr: mov cl,10 ! jmp call_cpm
c_rawio: mov cl,6 ! jmp call_cpm
c_set: mov cl,148 ! jmp call_cpm
c_write: mov cl,2 ! jmp call_cpm
c_writestr: mov cl,9 ! jmp call_cpm
f_open: mov cl,15 ! jmp call_cpm
f_parce: mov cl,152 ! jmp call_cpm
f_read: mov cl,20 ! jmp call_cpm
l_attach: mov cl,158 ! jmp call_cpm
l_writeblk: mov cl,112 ! jmp call_cpm
p_cli: mov cl,150 ! jmp call_cpm
p_create: mov cl,144 ! jmp call_cpm
p_delay: mov cl,141 ! jmp call_cpm
p_priority: mov cl,145 ! jmp call_cpm
p_termcpm: mov cl,0 ! jmp call_cpm
q_cread: mov cl,138 ! jmp call_cpm
q_delete: mov cl,136 ! jmp call_cpm
q_make: mov cl,134 ! jmp call_cpm
q_open: mov cl,135 ! jmp call_cpm
q_read: mov cl,137 ! jmp call_cpm
q_write: mov cl,139 ! jmp call_cpm
s_bios: mov cl,50 ! jmp call_cpm
t_seconds: mov cl,155 ! jmp call_cpm
call_cpm: int 224
ret
; set up data segment groups
dgroup group d4,d0,d1,d2,d3 ; dx is used a name of a data
; group, don't be concerned
; about their meaning.
d4 dseg
r dw 0 ; storate for rand. number seed
; Time of day structure
time_of_day dw 0
hour db 0
min_sec dw 0
; Signon message clears screen, disables cursor, and displays
; device status display header. It uses the escape sequences for the IBM
; PC, it also works on a Z-19/29
signon db 1bh,'E',1bh,'f',cr,lf
db ' Device Controller Status',cr
db lf,lf,lf
db ' Device',cr,lf
db ' 0 1 2 3',cr,lf,'$'
; Device status message and table. Each sub-process will toggle one
; byte in this message from '1' to a '0' of vise-versa, depending on
; what the new 'status' of the device is.
status_mess db 'State '
status db 48,' '
db 48,' '
db 48,' '
db 48,cr,'$'
; Abort flag. This byte is set to 1 by the parent process when it
; wants the sub-processes to stop.
abort db 0
; This message is displayed on termination of the parent process.
; (It re-enables the cursor)
exit_mess db cr,lf,lf,1bh,'e$'
; declarations for each of the sub-process process descriptors, refer
; to the CCP/M Programmer's Reference Guide for complete description of
; the PD fields
; process descriptor 0
pd0 dw offset pd1,0 ; link, thread fields
db 0,200,0,0 ; status, priority, flag fields
pd0_name db 'SP0 ' ; sub-process name
pd0_uda dw 0 ; offset to UDA
; remaining fields are initialized to 0
dw 0,0,0,0,0,0,0
pd0_cns db 0,0,0,0,0,0
dw 0,0,0,0,0
; process descriptor 1
pd1 dw pd2,0
db 0,200,0,0
pd1_name db 'SP1 '
pd1_uda dw 0
dw 0,0,0,0,0,0,0
pd1_cns db 0,0,0,0,0,0
dw 0,0,0,0,0
; process descriptor 2
pd2 dw pd3,0
db 0,200,0,0
pd2_name db 'SP2 '
pd2_uda dw 0
dw 0,0,0,0,0,0,0
pd2_cns db 0,0,0,0,0,0
dw 0,0,0,0,0
; process descriptor 3
pd3 dw 0,0
db 0,200,0,0
pd3_name db 'SP3 '
pd3_uda dw 0
dw 0,0,0,0,0,0,0
pd3_cns db 0,0,0,0,0,0
dw 0,0,0,0,0
; Declarations for each of the sub-process UDA's, refer to the CCP/M
; Programmer's Reference Guide for description of the UDA fields.
; user date area 0
d0 dseg para ; set to page boundary
uda0 rw 16
dw 0
bx_reg0 dw 0
dw 0,0,0,0,0
rw 3
dw init_sp0
dw 0,0,0,0,0,0,0,0,0,0,0,0,0
init_cs0 dw codeseg
init_ds0 dw d0
init_es0 dw d0
init_ss0 dw d0
dw 0,0,0,0,0,0,0,0
rw 0ffh-67h
rw 20
init_sp0 dw sub_proc
cs_init0 dw codeseg,0
d1 dseg para
; user date area 1
uda1 rw 16
dw 0
bx_reg1 dw 1
dw 0,0,0,0,0
rw 3
dw init_sp1
dw 0,0,0,0,0,0,0,0,0,0,0,0,0
init_cs1 dw codeseg
init_ds1 dw d1
init_es1 dw d1
init_ss1 dw d1
dw 0,0,0,0,0,0,0,0
rw 0ffh-67h
rw 20
init_sp1 dw sub_proc
cs_init1 dw codeseg,0
d2 dseg para
; user date area 2
uda2 rw 16
dw 0
bx_reg2 dw 2
dw 0,0,0,0,0
rw 3
dw init_sp2
dw 0,0,0,0,0,0,0,0,0,0,0,0,0
init_cs2 dw codeseg
init_ds2 dw d2
init_es2 dw d2
init_ss2 dw d2
dw 0,0,0,0,0,0,0,0
rw 0ffh-67h
rw 20
init_sp2 dw sub_proc
cs_init2 dw codeseg,0
d3 dseg para
; user date area 3
uda3 rw 16
dw 0
bx_reg3 dw 3
dw 0,0,0,0,0
rw 3
dw init_sp3
dw 0,0,0,0,0,0,0,0,0,0,0,0,0
init_cs3 dw codeseg
init_ds3 dw d3
init_es3 dw d3
init_ss3 dw d3
dw 0,0,0,0,0,0,0,0
rw 0ffh-67h
rw 20
init_sp3 dw sub_proc
cs_init3 dw codeseg,0
end