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