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

PROCEDURE
Get     PSHH    R0      ; <--\  procedure  
        PSHH    R1      ;     | must be 
        PSHH    R2      ;     | completely
        PSHH    R3      ;     | transparent
        PSHH    R4      ;     |
        PSHH    R5      ; <--/

        MOVB  A,R0              ; get InBuf index
        CMPB  #'#',InBuf[R0]    ; IF the last character of InBuf
        BREQ  ignore            ;    is already a '#' THEN --> ignore
        MOVB  B,R1              ; IF InBuf has a complete string
        CMPB  #0,WorkBuf[R1]    ;    not yet copied to WorkBuf 
        BRNE  ignore            ; THEN --> ignore
        INPB  22h,R2            ; 
        CMPB  #'#',R2           ; IF IN register contains a '#'
        BRNE  skip              ;
        ADDB  #1,R0             ; increment [i]
        MOVB  #'#',InBuf[R0]    ; THEN put the '#' in InBuf
        MOVB  R0,A              ; store [i]
        BRUN  exit_G            ;
skip    CMPB  #10,R0            ; IF the number of characters in
        BUGE  ignore            ;    Inbuf is >= 10 THEN --> ignore
                                ; otherwise
        ADDB  #1,R0             ; increment InBuf index
        INPB  22h,InBuf[R0]     ; (Inbuf) = ASCII code of input char
                                ; [22h = input data reg add]
        MOVB  R0,A              ; store InBuf Index
        BRUN  exit_G

ignore  INPB  22h,trash         ; trash = ASCII code of input char
                                ; [22h = input data reg add]
exit_G  POPH    R5      ; <--\
        POPH    R4      ;     |
        POPH    R3      ;     |
        POPH    R2      ;     |
        POPH    R1      ;     |
        POPH    R0      ; <--/
        IRET
ENDP

PROCEDURE
Put     PSHH    R0      ; <--\  procedure
        PSHH    R1      ;     | must be 
        PSHH    R2      ;     | completely
        PSHH    R3      ;     | transparent
        PSHH    R4      ;     |
        PSHH    R5      ; <--/

        MOVB  C,R0              ; get OutBuf index
        CMPB  #0,OutBuf[R0]     ; IF Outbuf[i] = 0 (meaning done)
        BREQ  disable           ; THEN --> disable
        OUTB  OutBuf[R0],24h    ; (Outbuf) = ASCII code of input char
                                ; [24h = output data reg add]
        ADDB  #1,R0             ; increment OutBuf index
        MOVB  R0,C              ; store OutBuf Index
        BRUN  exit_P            ; skip disable instruction
disable INTF  1011b             ; enable input interrupts only

exit_P  POPH    R5      ; <--\
        POPH    R4      ;     |
        POPH    R3      ;     |
        POPH    R2      ;     |
        POPH    R1      ;     |
        POPH    R0      ; <--/
        IRET
ENDP

PROGRAM Lab7
        Stack   DH      32      
        A       DB      (0)     ; variable declarations
        B       DB      (0)
        C       DB      (1)
        InBuf   DB      12
        WorkBuf DB      12
        OutBuf  DB      12
        trash   DB      (0)

        INTF  0                 ; 1. Disable all interrupts
        OUTB  #00110011b,26h    ; 2. initialize IO interface
                                ;    [26h = control register]
; bits 0 & 1 = 11b --> output & input mode = 8-bit
; bit 4      = 1b  --> output interrupt level 2 enabled
; bit 5      = 1b  --> input interrupt level 3 enabled

        MOVH  #0,8              ; 3. initialize interrupt vectors:
        MOVH  #Put,10           ; --> character out
        MOVH  #0,12             ;    
        MOVH  #Get,14           ; --> character in
        
        ;  /--------------------------------------------\
        ; |  initialize InBuf, WorkBuf, OutBuf, A, B, C  |
        ;  \--------------------------------------------/
begin   MOVB  #0,A
        MOVB  #0,B
        MOVB  #1,C
        SUBH  R5,R5
array1  CMPH  #13,R5
        BUGE  array2
        MOVB  #0,InBuf[R5]
        ADDH  #1,R5
        BRUN  array1
array2  SUBH  R5,R5

reset2  CMPH  #13,R5
        BUGE  array3
        MOVB  #0,WorkBuf[R5]
        ADDH  #1,R5
        BRUN  reset2
array3  SUBH  R5,R5
reset3  CMPH  #13,R5
        BUGE  ok
        MOVB  #0,OutBuf[R5]
        ADDH  #1,R5
        BRUN  reset3

ok      INTF  1011b             ; 4. enable only input interrupts

        ;  /---------------------------------------------\
        ; | Loop:                                         |
        ; | Delay until a complete string has been read   |
        ; | into the input buffer (InBuf)                 |
        ;  \---------------------------------------------/
loop    SUBH  R0,R0     ; clear R0
        MOVB  A,R0      ; get InBuf index
        CMPB  #'#',InBuf[R0]    ; look for a '#' character
        BREQ  if        ; IF InBuf[i] = '#' character 
                        ; THEN --> if
        BRUN  loop      ; otherwise --> loop

        ;  /-------------------------------------------\
        ; | IF the input string consists of only a      |
        ; | single '#' THEN halt program execution      |
        ;  \-------------------------------------------/
if      INTF  0         ; disable input interrupts
        MOVB  A,R0      ; get InBuf index
        SUBB  #1,R0     ; [i] = [i] - 1
        CMPB  #0,InBuf[R0]      ; look at previous character
        BREQ  done      ; IF previous character = 0 
                        ; THEN halt program execution

        ;  /------------------------------------------\
        ; | copy the string in InBuf into the work     |  
        ; | buffer (WorkBuf)                           |
        ;  \------------------------------------------/
        SUBH  R0,R0     ; use R0 as index [i]
I_to_W  CMPB  #13,R0    ;
        BUGE  replace   ; IF [i] >= 13 THEN --> replace
        MOVB  InBuf[R0],WorkBuf[R0]
                        ; copy string in InBuf to WorkBuf
        MOVB  R0,B      ; B = current index of WorkBuf
        ADDB  #1,R0     ; increment index [i]
        BRUN  I_to_W    ;

replace INTF  1011b     ; enable input interrupts

        ;  /---------------------------------------------\
        ; | replace each digit in WorkBuf with a 'd'.     |
        ; | replace each lowecase letter with an 'l'.     |
        ; | replace each uppercase letter with a 'u'.     |
        ; | replace all other characters with an 'o'.     |
        ;  \---------------------------------------------/
        MOVH  #1,R0     ; use R0 as index [i]
next0   MOVB  WorkBuf[R0],R1    ; get character at [i]
        CMPB  #0,R1     ; 
        BREQ  outwait   ; IF [i] = 0 THEN --> outwait
        CMPB  #2Fh,R1   ; 
        BUGT  next1     ; IF ASCII value > '/' THEN --> next1
        MOVB  #'o',WorkBuf[R0]  ; otherwise replace with 'o'
        BRUN  next_char ; 
next1   CMPB  #39h,R1   ; 
        BUGT  next2     ; IF ASCII value > '9' THEN --> next2
        MOVB  #'d',WorkBuf[R0]  ; otherwise replace with 'd'
        BRUN  next_char ; 
next2   CMPB  #40h,R1   ; 
        BUGT  next3     ; IF ASCII value > '@' THEN --> next3
        MOVB  #'o',WorkBuf[R0]  ; otherwise replace with 'o'
        BRUN  next_char ;
next3   CMPB  #5Ah,R1   ; 
        BUGT  next4     ; IF ASCII value > 'Z' THEN --> next4
        MOVB  #'u',WorkBuf[R0]  ; otherwise replace with 'u'
        BRUN  next_char ; 
next4   CMPB  #60h,R1   ; 
        BUGT  next5     ; IF ASCII value > '`' THEN --> next5
        MOVB  #'o',WorkBuf[R0]  ; otherwise replace with 'o'
        BRUN  next_char ; 
next5   CMPB  #7Ah,R1   ; 
        BUGT  next6     ; IF ASCII value > 'z' THEN --> next6
        MOVB  #'l',WorkBuf[R0]  ; otherwise replace with 'l'
        BRUN  next_char ;
next6   MOVB  #'o',WorkBuf[R0]  ; otherwise replace with 'o'

next_char     NOOP
        ADDB  #1,R0     ; increment [i]
        BRUN  next0     ; replace next character

        ;  /-----------------------------------------\
        ; | delay until the output buffer (outBuf)   |
        ; | is empty                                 |
        ;  \-----------------------------------------/

outwait INPB  20h,R2    ; 20h = status register address
        TSTB  #1b,R2    ; OUT register: 1 = empty, 0 = full
        BREQ  outwait   ; IF full THEN --> outwait

        ;  /-----------------------------------------\
        ; | copy the string in WorkBuf into OutBuf    |
        ;  \-----------------------------------------/
        SUBH  R0,R0     ; use R0 as index [i]
copy    CMPB  #13,R0    ;
        BUGE  output    ; IF [i] >= 13 THEN --> output
        MOVB  WorkBuf[R0],OutBuf[R0]
                        ; copy string in WorkBuf to OutBuf
        ADDH  #1,R0     ; increment [i]
        BRUN  copy      ; copy next character
       
output  INTF  1010b     ; enable output interrupts
        OUTB  #0b,24h   ; [24h = output data reg add]
        BRUN  begin     ; go back to beginning
done    HALT            ; input string = '#' only
ENDP
END