/ A second demonstration interrupt driven program.
/
/ This program has to read characters from keyboard,
/ non-digit characters will get discarded, sequences of digits are
/ interpreted as representing (unsigned) decimal numbers --- a number conversion
/ is performed, the value read is stored in an array and added into a sum
/
/ the program terminates when the sum exceeds one thousand.
/
/ the program has to monitor the clock while doing other work
/
/ the characters read must be stored in a buffer, they get fetched from there
/ when needed by the processing routines.
/ Since the multiply by shift-and-add is slow, the buffer tends to fill up
/ when digits are being processed; but, its quickly emptied of any non-digit
/ characters
*0
/ save program counter on interrupt
0
jmp i pints
pints, inthnd
accsav, 0
lnksav, 0
/
*20
ticks, 0 / count of clock ticks
intsrd, intary / array where integer values read are stored
intcnt, 0 / count of integers read
total, 0 / sum of integers read
inbuff, chrbuf / array that constitutes circular input buffer
pptr, 0 / " pointers " into buffer for producer and
cptr, 0 / consumer
nchar, 0 / character
done, 0 / boolean flag. set when want to terminate
/
/ the following variables belong to the multiplication routines
/
*160
mplr, 0 / multiplier
mpand, 0 / multiplicand
prod, 0 / single length product
temp, 0 / work space used by multiply routine
divsr, 0 / divisor
divdn, 0 / dividend
quot, 0 / quotient
rem, 0 / remainder
kd12, 14 / 12 decimal, the number of bits
kd10, 12 / 10 decimal
kd100, 144 / 100 decimal
kd1000, 1750 / 1000 decimal
cntr, 0 / used when looping as a counter
*200
start, cla cll
dca intcnt / zero out all variables
dca total
dca done
dca ticks
dca cptr
dca pptr
clkt / start clock
ion / enable interrupts
loop, jms i pnxtch / get a character
jms isdig / check if a digit
skp / if it wasn't, discard the character
jms readnm / if it was, start the new number
cla cll
tad total / check for termination
cia
tad kd1000
sma cla
jmp loop
/ have read enough
iof
hlt
pnxtch, nxtch
/
/ readnm:
/ entered when have read first digit
/ of a number
/ complete reading characters and combining them
/ in to form a number
readnm, 0
cla cll
dca number
lrdnm, cla cll / convert character to numeric
tad czero
cia
tad nchar
dca n
/ now need to multiply current number by 10 decimal
tad number
dca mpand
tad kd10
dca mplr
jms i pmult
/ assume that no chance of exceeding numbers allowed!
tad prod
tad n
dca number
/ get next character
jms i pnxtch
/ check if digit
jms isdig
skp / if it wasn't then quit
jmp lrdnm / if it was a digit, continue building number
/ number is finished,
/ store it away
/ have to index into an array
tad intsrd / base address
tad intcnt / + index value
dca point / = required address
tad number
dca i point
/ increment count
isz intcnt
nop
/ add number into total
tad number
tad total
dca total
jmp i readnm
number, 0
n, 0
point, 0
pmult, mult
/
/ isdig:
/ check on character in "char"
/ is it a digit, (i.e. >= '0', <='9'),
/ if so return its numeric value in acc
/ and MODIFY RETURN address
/
/ so, will be returning to address immediately
/ following call if its not a digit (and acc will be zero)
/ but returning to address subsequent to that if it
/ is a digit
/
isdig, 0
cla cll
tad czero
cia
tad nchar
spa cla
jmp i isdig / its less than zero character
tad nchar
cia
tad cnine
spa cla
jmp i isdig
/ its a digit as in correct range of character values
isz isdig
nop
jmp i isdig
czero, 60 / value representing '0'
cnine, 71 / value representing '9'
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*400
/ Here is the interrupt handler
inthnd, dca accsav
rar
dca lnksav
/ saves completed, now skip chain
clksf
skp
jmp clksrv
ksf
skp
jmp keysrv
hlt / unknown interrupt
/ here, have return from interrupt
xit, cla cll
/ restore registers
tad lnksav
ral
tad accsav
/ re-enable interrupts
ion
/ do return
jmp i 0
/
/ clock service routine
clksrv, clkcf / clear clock flag
isz ticks
nop
jmp xit
/ keyboard service routine
keysrv, krb
dca temp1
/ need to index into array
tad inbuff / base address
tad pptr / + index
dca temp2 / = required address
tad temp1
dca i temp2 / character stored in "inbuff[pptr]"
tad pptr
iac
/ here we cheat a little, use a masking operation
/ to force pptr to stay in range 0-177 octal
and m177
dca pptr
jmp xit
m177, 0177
temp1, 0
temp2, 0
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*600
nxtch, 0
/ wait till there are characters
nxtl, cla cll
tad cptr
cia
tad pptr
sna cla
jmp nxtl / if pointers are equal then no characters yet
/ need to index into array
tad inbuff / base address
tad cptr / + index
dca ntemp2 / = required address
tad i ntemp2
dca nchar
tad cptr
iac
/ here we cheat a little, use a masking operation
/ to force pptr to stay in range 0-177 octal
and nm177
dca cptr
jmp i nxtch
nm177, 0177
ntemp2, 0
/ Here we have a "shift and add" multiply routine.
/
/ Several simplifying assumptions:
/ 1) its intended only for positive numbers (so not
/ going to worry about two's complement notation
/ for integers).
/ 2) its intended only for small numbers (the product
/ of two 12-bit numbers can require 24-bits,
/ that would mean simulating a double length
/ register which is practical but tiresome,
/ so assume that will only be working with
/ small numbers and that product will be
/ represented in 12-bits; no attempt made
/ to detect overflow).
/ 3) note the crude way of passing the arguments (multiplier
/ and multiplicand) via page 0 locations.
mult, 0
cla cll
/ first, set up a loop that will take us through the
/ 12 (decimal) bits of the words to be multiplied.
tad kd12
cia
dca cntr
tad mpand
dca temp
/ zero the product
dca prod
lmult, cla cll
/ isolate next bit of multiplier
tad mplr
rar
dca mplr
/ test if a 1, for then need to add in another
/ partial product
snl
jmp mult1 / that bit was a zero, so ignore
tad temp
tad prod
dca prod
/ to mult1, now shift temp left as considering next power
/ of 2
mult1, cla cll
tad temp
ral
dca temp
/ check if have finished the loop
isz cntr
jmp lmult
emult, jmp i mult
/
*1000
chrbuf, 0
*1200
intary, 0
$