MIT PDP-10 'Info' file converted to Hypertext 'html' format by Henry Baker

Previous Up Next

Arithmetic Calculator Program.

This program will read an arithmetic expression composed of numbers and the operators +, -, * and /, compute the value and type the result. It shows how to read and print numbers. It does not know about operator precedence; it does operations from left to right always.
        TITLE   NUM
FL=0
A=1
B=2
C=3
D=4
P=17

CHTTYI==1
CHTTYO==2

;FLAG NAMES
NEGF==1
DIGF==2

PDLLEN==100
PDL:    BLOCK PDLLEN
OP1:    0
X1:     0

LINBUF: BLOCK 30
LINBFE::

LINPTR: 0

START:  MOVE P,[-PDLLEN,,PDL-1]
                                ;Open TTY channels.
        .CALL [SETZ ? SIXBIT/OPEN/
                [.UAI,,CHTTYI] ? [SIXBIT/TTY/] ((SETZ))]
         .LOSE %LSFIL
        .CALL [SETZ ? SIXBIT/OPEN/
                [.UAO,,CHTTYO] ? [SIXBIT/TTY/] ((SETZ))]
         .LOSE %LSFIL
START1: PUSHJ P,GETLIN          ;Read in a line of input.
        MOVE A,[440700,,LINBUF]
        MOVEM A,LINPTR          ;Set up to fetch chars from the line.
        PUSHJ P,EVAL            ;Parse and evaluate expression.
        PUSHJ P,DECOUT          ;Print the answer.
        MOVEI A,[ASCIZ/
/]
        PUSHJ P,OUTSTR
        JRST START1

;Read and evaluate an expression.  Value returned in A.
;Clobbers B.
EVAL:   PUSHJ P,DECIN           ;Read one number.
        MOVEM B,OP1             ;Save the number.
EVAL1:  MOVEI B,0
        CAIN A,"+               ;Consider the operation character:
         MOVE B,[ADD B,OP1]     ;B gets an instruction to do that operation.
        CAIN A,"-
         MOVE B,[SUB B,OP1]
        CAIN A,"*
         MOVE B,[IMUL B,OP1]
        CAIN A,"/
         MOVE B,[IDIV B,OP1]
        JUMPE B,EVALX           ;If B is still 0, the terminator
                                ;was not an arith op, so it ends
                                ;the expression or is illegal.
        MOVEM B,X1              ;It is an arith op, so save the instruction.
        PUSHJ P,DECIN           ;Read the second operand.
        EXCH B,OP1              ;B gets first op, OP1 gets second operand.
        XCT X1                  ;Compute result of operation, in B.
        MOVEM B,OP1             ;Save it as first operand of next operation.
        JRST EVAL1              ;A has terminator of second operand,
                                ;which is the next operation.

;Come here on number terminated by char not an arith op.
EVALX:  JUMPN A,ERR             ;Should be end of line, or it's an error.
        MOVE A,OP1              ;Otherwise, last saved value is value of exp.
        POPJ P,

;Print an error message if we see something we don't recognize.
ERR:    MOVEI A,[ASCIZ/Unrecognized character in expression: /]
        PUSHJ P,OUTSTR
        LDB A,LINPTR            ;Print the offending character
        .IOT CHTTYO,A           ;as part of the error message.
        MOVEI A,[ASCIZ /
/]
        PUSHJ P,OUTSTR
        JRST START1

;Read a signed decimal number out of the line, returning number in B
;and terminating character in A.
DECIN:  TRZ FL,NEGF!DIGF        ;No minus, no digit seen yet.
        MOVEI B,0
DECIN1: ILDB A,LINPTR           ;Fetch next character of line.
        CAIL A,"0
         CAILE A,"9
          JRST DECIN2           ;Jump if character not a digit.
        IMULI B,10.             ;Else accumulate this digit into the number.
        ADDI B,-"0(A)           ;Note that we convert the digit into its value.
                                ;("0 into the value 0, "1 into 1).
        TRO FL,DIGF             ;Set flag saying non-null number seen.
        JRST DECIN1

DECIN2: CAIN A,"-
         JRST DECIN3            ;Jump on minus sign.
        TRNN FL,DIGF            ;Anything else: if we saw a number,
         POPJ P,                ;negate it if it began with a minus sign.
DECIN4: TRZE FL,NEGF
         MOVN B,B
        POPJ P,

;Come here after reading a minus sign.
DECIN3: TRNE FL,DIGF            ;Does it follow a number?
         JRST DECIN4            ;Yes.  This must be a binary minus.
        TRC FL,NEGF             ;This must be unary minus.
                                ;Complement flag that number is negative.
        JRST DECIN1             ;(So that two minus signs cancel out).

;Print number in A, positive or negative, in decimal.
;Clobbers A and B.
DECOUT: JUMPGE A,DECOT1
        .IOT CHTTYO,["-]        ;If number is negative, print sign.
        CAMN A,[400000,,]       ;Smallest negative number is a pain:
         JRST DECOT2            ;its absolute value cannot fit in one word!
        MOVM A,A                ;Else get abs val of negative number and print.
DECOT1: IDIVI A,10.
        HRLM B,(P)              ;Save remainder in LH of stack word
                                ;whose RH contains our return address.
        SKIPE A                 ;If quotient is nonzero,
         PUSHJ P,DECOT1         ;print higher-order digits of number.
        HLRZ A,(P)              ;Get back this remainder (this digit).
        ADDI A,"0
        .IOT CHTTYO,A
        POPJ P,

;Print the abs value of the largest negative number.
DECOT2: MOVEI A,[ASCIZ /34359738368/]
        JRST OUTSTR

;Copy the GETLIN and OUTSTR subroutines here.

        END     START

NOTES