/ 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 $