/ / FIND-MAX / / This is a simple demonstration program for the / simul8 simulator. / / The program is to read from input a sequence / of numbers; it is to find the largest number in this sequence and / the number of items in the sequence. These values are then / to be printed / / The input should consist of a sequence of small positive / numbers (in decimal) separated by spaces and terminated by / a number 0 / / The program does not attempt to validate the input, check / for overflow or perform and other testing. / / The program contains shift-add multiply and corresoponding divide / subroutines / *20 char, 0 / next character read or written nchar, 0 / value as number if character was a digit num, 0 / number being worked on max, 0 / maximum found so far items, 0 / count of numbers processed. *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 max dca items / main loop, get next character, echo it loop, jms i pget jms i pput1 / test if it's a digit, if so then it starts a number and must read numeric / data, if not a digit --- then go back and collect next character input jms i pisdig jmp loop dca nchar / have a number, complete reading process jms readnm / is it zero, if so finished tad num sna jmp quit / is it maximum? cia tad max sma cla jmp upda /no, seen bigger / yes, replace max tad num dca max / update count of items upda, isz items nop / loop back to get another number jmp loop / to quit, found the zero at end of input. quit, jms i pfinis hlt pisdig, isdig pfinis, finis pput1, put pget, get / - - - - - - - - - - - - - / readnm: / entered when have read first digit / of a number / complete reading characters and combining them / in to form a number readnm, 0 / initialize number to value of digit character just read tad nchar dca num / now main loop of readnumber lrdnm, jms i pget / get next character jms i pput1 jms i pisdig / is it a digit jmp i readnm / no, so finished dca nchar / yes, so save it / now need to multiply current number by 10 decimal tad num dca mpand tad kd10 dca mplr jms i pmult tad prod tad nchar dca num jmp lrdnm pmult, mult *400 / 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 / / and here is a shift and subtract division routine, / much the same limitations as in the multiply div, 0 cla cll dca quot dca rem tad divdn dca temp tad kd12 cia dca cntr ldiv, cla cll / move next bit into rem tad temp ral dca temp tad rem ral dca rem / do subtraction, tad divsr cia tad rem / if result -ve, dont't set bit in quotient spa jmp div1 dca rem / set a 1 in link cll cml jmp div2 / set a 0 in link div1, cla cll / now move bit into quotient div2, tad quot ral dca quot cla cll / check if have finished loop isz cntr jmp ldiv ediv, jmp i div *600 / Basic flag-driven i/o / / get: read character from keyboard (normal wait for key stroke) / and store in "char" get, 0 cla cll lget, ksf jmp lget krb dca char jmp i get / put: print character held in "char" / (send the character, wait till notified that it got off / safely) put, 0 cla cll tad char tls lput, tsf jmp lput cla cll jmp i put / / / msg: print a message, / on entry, acc should contain address of where / some characters forming message are stored / characters should be stored one per word / and terminated by a word containing zero. msg, 0 dca mptr lmsg, tad i mptr sna jmp i msg dca char jms put isz mptr nop jmp lmsg mptr, 0 / / / 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 zero cia tad char spa cla jmp i isdig / its less than zero character tad char cia tad nine spa cla jmp i isdig / its a digit as in correct range of character values / convert from character form to numeric tad zero cia tad char isz isdig nop jmp i isdig zero, 60 / value representing '0' nine, 71 / value representing '9' *1000 / finis: / end marker in input encountered / / put some newlines after the echoed input / print message "# read : " / then print item-count / then print message representing couple of newlines / then print "Largest : " / print max / print newlines finis, 0 tad amsg2 jms i pmsg tad amsg1 jms i pmsg / now print count tad items jms i pprnum tad amsg2 jms i pmsg tad amsg3 jms i pmsg / largest value tad max jms i pprnum tad amsg2 jms i pmsg jmp i finis pprnum, prnum pmsg, msg amsg1, msg1 amsg2, msg2 amsg3, msg3 msg1, 43 / # 40 / space 162 / r 145 / e 141 / a 144 / d 40 40 72 / : 40 0 msg2, 15 15 12 0 msg3, 114 / L 141 / a 162 / r 147 / g 145 / e 163 / s 164 / t 40 72 40 0 *1200 / An oversimplified number printing routine / / Its a bit specific to this problem, / numbers can be assumed to be smallish positive / values. / / will divide by 1000 (decimal) and convert quotient / to character representing number of thousands / / take remainder, divide by 100 (decimal) print result / / and so forth, / / prnum, 0 dca divdn dca chflag / do the divides by 1000 tad kd1000 dca divsr jms i pdiv / look at result, if zero don't want to print anything tad quot sna jmp prn1 / but if have a thousands digit, then convert value to character form / and print tad przero dca char jms i pput / and note that we have printed some characters isz chflag nop / / now deal with the hundreds prn1, tad rem dca divdn tad kd100 dca divsr jms i pdiv / again do we have a hundreds digit, or have we already printed a / thousands digit / if we've already printed a thousands digit, best print hundreds digit / even if its a zero tad chflag sza cla jmp prn1c / if no characters printed so far, again check to see if this is a zero / in which case will omit tad quot sna cla jmp prn2 / prn1c, convert hundreds digit to character form and print prn1c, tad quot tad przero dca char jms i pput isz chflag nop / deal with tens in like manner prn2, tad rem dca divdn tad kd10 dca divsr jms i pdiv / usual checks regarding printing of leading zeros tad chflag sza cla jmp prn2c tad quot sna cla jmp prn3 prn2c, tad quot tad przero dca char jms i pput prn3, tad rem tad przero dca char jms i pput jmp i prnum pput, put pdiv, div przero, 60 chflag,0 $