UNIT  CmpSci 201 Lab Exercise #6
; Robert S. Laramee
; cs201
; start date 2 Nov 1996

; StatReg  EQU   20h        ; stat reg port add
; InReg    EQU   22h        ; input data reg port add
; OutReg   EQU   24h        ; output data reg port add
; CtlReg   EQU   26h        ; control register port add

; In8      EQU   00000010b  ; 8-bit input
; Out8     EQU   00000001b  ; 8-bit output

PROGRAM Lab6
        Stack   DH      32      
        A       DB      ('a', 'a', 'a', 'a', 'a', 'a') ; 1st number
        B       DB      ('b', 'b', 'b', 'b', 'b', 'b') ; 2nd number

begin   SUBH  R5,R5
array1  CMPH  #6,R5
        BUGE  array2            ; IF [i] >= 6 THEN --> array2
        MOVB  #'a',A[R5]        ; reset array
        ADDH  #1,R5             ; increment [i]
        BRUN  array1            ;

array2  SUBH  R5,R5
reset2  CMPH  #6,R5
        BUGE  proceed           ; IF [i] >= 6 THEN --> proceed
        MOVB  #'b',B[R5]        ; reset array      
        ADDH  #1,R5             ; increment [i]
        BRUN  reset2            ;

proceed OUTB  #00000010b,26h    ; set bit 2 to 1 in cont reg
                                ; meaning input mode = 8-bit

        SUBH  R0,R0     ; clear R0, use for status reg
        SUBH  R1,R1     ; clear R1, use for I/O character
        SUBH  R2,R2     ; clear R2, use as 1st_number total
        SUBH  R3,R3     ; clear R3, holds remainder of R2
        SUBH  R4,R4     ; clear R4  use as 2nd_number total
        SUBH  R5,R5     ; use R5 as index, [i]

;  ################
;  #  1st number  #
;  ################
num_1   CMPH  #6,R5     ; look at 6 vs [i]
        BUGT  Error     ; IF [i] > 6 THEN --> error
inwait1 INPB  20h,R0    ; R0 = status register
                        ; [20h = status register address]
        TSTB  #10b,R0   ; test bit 2 of status
        BREQ  inwait1   ; IF IN reg empty THEN --> inwait1
                        ; otherwise
        INPB  22h,R1    ; R1 = ASCII code of input char
                        ; [22h = input data reg add]

        CMPB  #'-',R1   ; look for a minus sign
        BREQ  ngtv1     ; IF input = '-' THEN --> ngtv1
        CMPB  #',',R1   ; look for a comma
        BREQ  next1     ; IF input = ',' THEN --> next1
        CMPB  #'.',R1   ; look for a period, '.'
        BREQ  verify    ; IF input = '.' THEN --> verify

        SUBB  #30h,R1   ; otherwise, convert ASCII -> actual #
ngtv1   MOVB  R1,A[R5]  ; store input character in A[i]
        ADDH  #1,R5     ; increment index [i]
        BRUN  num_1     ; goto next digit

;  ################
;  #  2nd number  #
;  ################
next1   SUBH  R0,R0     ; clear R0, for status reg
        SUBH  R1,R1     ; clear R1, for input/output char
        SUBH  R5,R5     ; clear R5, for index [i]

num_2   CMPH  #6,R5     ; look at 6 vs [i]
        BSGT  error     ; IF [i] > 6 THEN --> error
inwait2 INPB  20h,R0    ; R0 = stat reg
                        ; [20h = stat reg add]
        TSTB  #10b,R0   ; test bit 2 of status
        BREQ  inwait2   ; IF IN reg empty THEN --> inwait2
                        ; otherwise
        INPB  22h,R1    ; R1 = ASCII code of input char
                        ; [22h = input data reg add]

        CMPB  #'-',R1   ; look for a minus sign
        BREQ  ngtv2     ; IF input = '-' THEN --> ngtv2
        CMPB  #',',R1   ; look for a comma
        BREQ  error     ; IF input = ',' THEN --> error
        CMPB  #'.',R1   ; look for a period, '.'
        BREQ  verify    ; IF input = '.' THEN --> verify

        SUBB  #30h,R1   ; convert ASCII -> actual #
ngtv2   MOVB  R1,B[R5]  ; store input character in B[i]
        ADDH  #1,R5     ; increment index [i]
        BRUN  num_2     ; goto next digit

verify  SUBH  R5,R5     ; reset [i]
again1  CMPH  #5,R5     ;
        BSGT  next2     ; IF [i] > 5 THEN --> next2
        CMPB  #'-',A[R5];
        BREQ  skip1     ; IF A[0] = '-' THEN --> skip1
        ADDB  A[R5],R2  ; R2 = total 1st_num
        BULT  error     ; IF C = 1 THEN goto error
                        ; [input > 32,767]
skip1   ADDH  #1,R5     ; otherwise, increment index [i]
        CMPB  #'a',A[R5] 
        BREQ  next2     ; IF A[i] = 'a' THEN --> next2
        MULH  #10,R2    ; left one decimal place
        BRUN  again1    ; add next digit

next2   SUBH  R0,R0     ; use R0 as [i] because
again2  CMPH  #5,R0     ; R5 gets overwritten
        BUGT  add       ; IF [i] > 5 THEN --> add
        CMPB  #'-',B[R0];
        BREQ  skip2     ; IF B[0] = '-' THEN --> skip2
        CMPB  #'b',B[R0];
        BREQ  add       ; IF B[R0] = 'b' THEN --> add
        ADDB  B[R0],R4  ; R4 = total 2nd_num
        BULT  error     ; IF C = 1 THEN --> error
                        ; [input > 32,767]
skip2   ADDH  #1,R0     ; increment index [i]
        CMPB  #'b',B[R0];
        BREQ  add       ; IF B[R0] = 'b' THEN --> add
        MULH  #10,R4    ; left one decimal place
        BRUN  again2    ; add next digit

add     CMPB  #'-',A    ;
        BRNE  skip3     ; IF num_1 => 0 THEN --> skip3
        MULB  #-1,R2    ; otherwise, num_1 < 0
skip3   CMPB  #'-',B    ;
        BRNE  skip4     ; IF 2nd_num => 0 THEN --> skip4
        MULB  #-1,R4    ; otherwise num_2 < 0
skip4   ADDH  R2,R4     ; R4 = 1st_num + 2nd_num
        BROV  out_output; IF V = 1 THEN --> out_output
        BRNG  neg_output; IF N = 1 THEN --> neg_output
        BRUN  output    ; otherwise, --> output

; ##################
; # correct result #
; ##################
output  OUTB  #00000001b,26h    ; set bit 0 of cont reg = 1
                                ; meaning output mode = 8-bit
        SUBH  R5,R5     ; use R5 as num_of_digits pushed
        MOVH  R4,R2     ; R2 = result
        SUBH  R4,R4     ; clear R3
again3  DIVH  #10,R2    ; divide result by 10
                        ; remainder should be in R3
        ADDH  #30h,R3   ; convert actual num --> ASCII value
        PSHH  R3        ; push value on stack
        SUBH  R3,R3     ; clear R3 for next value
        ADDH  #1,R5     ; increment num_of_digits pushed
        ANDH  #0111111111111111b,R2
        CMPH  #0,R2     ;
        BREQ  display   ; IF R2 = 0 THEN goto display
        BRUN  again3    ; otherwise goto again3

display NOOP
again4  CMPH  #0,R5     ;
        NOOP            ; <--Print screen here
        BREQ  begin     ; IF #_of_digits = 0 THEN --> begin
        SUBH  R3,R3     ; clear R3 for next value
        POPH  R3        ; R3 = current ASCII value
       
outwait INPB  20h,R1    ; R1 = status register
                        ; [20h = add of status reg]        
        TSTB  #00000001b,R1
        BREQ  outwait   ; IF OUT reg empty THEN --> outwait
        OUTB  R3,24h    ; current ASCII value --> display
                        ; [24h = output data reg port address]
        SUBH  #1,R5     ; decrement num_of_digits
        BRUN  again4    ; display next digit

; ################
; # out of range #
; ################
out_output      OUTB  #00000001b,26h    ; set bit 0 of
                ; control reg = 1, meaning output mode = 8-bit       
                MOVB  #'?',R3           ;
outwait2        INPB  20h,R1    ; R1 = status reg
                                ; [20h = add of stat reg]        
        TSTB  #00000001b,R1
        BREQ  outwait2  ; IF OUT reg empty THEN --> outwait2
        OUTB  R3,24h    ; '#' --> display
                        ; [24h = output data reg port add]
        MOVB  #'-',R3           ;
outwait3        INPB  20h,R1    ; R1 = status register
                                ; [20h = add of stat reg]        
        TSTB  #00000001b,R1
        BREQ  outwait3  ; IF OUT reg empty THEN --> outwait3
        OUTB  R3,24h    ; '#' --> display
                        ; [24h = output data reg port add]
        MULB  #-1,R4
        BRUN  output

; ###################
; # negative output #
; ###################
neg_output      OUTB  #00000001b,26h    ; set bit 0 of
                ; cont reg to 1 meaning output mode = 8-bit       
                MOVB  #'-',R3           ;
outwait4        INPB  20h,R1    ; R1 = status register
                                ; [20h = address of stat reg]        
        TSTB  #00000001b,R1     ;
        BREQ  outwait4  ; IF OUT reg empty THEN --> outwait4
        OUTB  R3,24h    ; '#' --> display
                        ; [24h = output data reg port addr]
        MULB  #-1,R4    ;
        ADDH  #30h,R4   ; convert actual num --> ASCII value
        OUTB  R4,24h    ; current ASCII value --> display
                        ; [24h = output data reg port add]
        NOOP            ; <--Print screen here
        BRUN  begin

; #########
; # error #
; #########
error   OUTB  #00000001b,26h    ; set bit 0 of cont reg = 1
                                ; meaning output mode = 8-bit       
                MOVB  #'#',R3   ;
outwait5        INPB  20h,R1    ; R1 = status register
                                ; [20h = addr of stat reg]        
        TSTB  #00000001b,R1
        BREQ  outwait5  ; IF OUT reg empty THEN --> outwait5
        OUTB  R3,24h    ; '#' --> display
                        ; [24h = output data reg port addr]

        MOVB  #2Eh,R1   ; R1 = ascii code of '.'
        CMPB  #'.',R1   ; look for a period, '.'
        NOOP            ; <--Print screen here
        BREQ  begin     ; IF input = '.' THEN --> begin
END