PRTBYT, GETBYT and PACK

PRTBYT takes a byte and sends it to the serial TY as two hex ascii characters
The byte is entered in A, two characters are printed and A is saved.

0914   1E3B             ;		
0915   1E3B             ;       PRINT 1 HEX BYTE AS 2 ASCII CHAR'S
0916   1E3B             ;   
0917   1E3B 85 FC       PRTBYT  STA   TEMP                             
0918   1E3D 4A                  LSR   A           ; SHIFT CHAR RIGHT 4 BITS
0919   1E3E 4A                  LSR   A
0920   1E3F 4A                  LSR   A
0921   1E40 4A                  LSR   A
0922   1E41 20 4C 1E            JSR   HEXTA       ; CONVERT TO HEX AND PRINT
0923   1E44 A5 FC               LDA   TEMP        ; GET OTHER HALF
0924   1E46 20 4C 1E            JSR   HEXTA       ; CONVERT TO HEX AND PRINT
0925   1E49 A5 FC               LDA   TEMP        ; RESTORE BYTE IN A AND RETURN
0926   1E4B 60                  RTS   
0927   1E4C             ;
0928   1E4C 29 0F       HEXTA   AND   #$0F        ; MASK HI 4 BITS
0929   1E4E C9 0A               CMP   #$0A
0930   1E50 18                  CLC   
0931   1E51 30 02               BMI   HEXTA1
0932   1E53 69 07               ADC   #$07        ; ALPHA HEX
0933   1E55 69 30       HEXTA1  ADC   #$30        ; DEC HEX
0934   1E57 4C A0 1E            JMP   OUTCH       ; PRINT CHAR

What is happening here?

  • The byte in A is saved (917)
  • the high nibble is shifted to the lower nibble (918-921)
  • the nibble is converted to hex (922, calls hexta)
  • the byte is restored and the low nibble converted to hex
  • A is restored
    • hexta masks off low nibble (928)
    • convert A..F to ascii (929-932)
    • convert hex to ascii and print(933-934)

    GETBYT and PACK

    1148   1F9D             ;		
    1149   1F9D             ;       GET 2 HEX CHAR'S AND PACK 
    1150   1F9D             ;       INTO INL AND INH
    1151   1F9D             ;       X PRESERVED Y RETURNED = 0
    1152   1F9D             ;       NON-HEX WILL BE LOADED AS NEAREST HEX EQU
    1153   1F9D             ;
    1154   1F9D 20 5A 1E    GETBYT  JSR   GETCH
    1155   1FA0 20 AC 1F            JSR   PACK
    1156   1FA3 20 5A 1E            JSR   GETCH
    1157   1FA6 20 AC 1F            JSR   PACK
    1158   1FA9 A5 F8               LDA   INL
    1159   1FAB 60                  RTS
    1160   1FAC             ;		
    1161   1FAC             ;       SHIFT CHAR IN A INTO
    1162   1FAC             ;       INL AND INH 
    1163   1FAC             ;
    1164   1FAC C9 30       PACK    CMP   #$30       ; CHECK FOR HEX 
    1165   1FAE 30 1B               BMI   UPDAT2
    1166   1FB0 C9 47               CMP   #$47       ; NOT HEX EXIT
    1167   1FB2 10 17               BPL   UPDAT2
    1168   1FB4 C9 40               CMP   #$40       ; CONVERT TO HEX
    1169   1FB6 30 03               BMI   UPDATE
    1170   1FB8 18                  CLC   
    1171   1FB9 69 09               ADC   #$09
    1172   1FBB 2A          UPDATE  ROL   A
    1173   1FBC 2A                  ROL   A
    1174   1FBD 2A                  ROL   A
    1175   1FBE 2A                  ROL   A
    1176   1FBF A0 04               LDY   #$04       ; SHIFT INTO I/O BUFFER
    1177   1FC1 2A          UPDAT1  ROL   A
    1178   1FC2 26 F8               ROL   INL
    1179   1FC4 26 F9               ROL   INH
    1180   1FC6 88                  DEY   
    1181   1FC7 D0 F8               BNE   UPDAT1
    1182   1FC9 A9 00               LDA   #$00       ; A=0 IF HEX NUM
    1183   1FCB 60          UPDAT2  RTS
    

    What is happening here?

    GETBYT
    The GETBYT routine is used in the TTY part of the KIM-1 monitor to enter two hex characters (0..9 and A..F) and pack it into one byte.

    • read the first character (1154)
    • pack it into INL lower nibble (1155)
    • read the second character (1156)
    • pack it into INL, shifting the lower nibble to high and shifting in the second nibble (1157)
    • return byte from INL to A

    PACK

    • check if < '0' and error out with A > 0 (1164-1165)
    • check if > ‘F’ and error out with A > 0 (1166-1167)
    • if A..F add $09 (1168-1171)
    • shift in nibble via INH and INL
    • return zero if valid hex but with invalid Z flag

    Note that the range between ‘9’ and ‘A’ is not checked, so those are taken as valid hex characters.
    The PACK routine accepts ‘:’– ‘?’, $3A .. $3F as valid hex characters A ..F.

    KIM
    0200 A9 ;;
    00BB 00 ::
    00AA 00 ????
    FFFF 1C
    

    The ASCII encoding is arranged so that adding 9 to ‘A’–’F’ aligns them perfectly with the desired hexadecimal nibble after four left rotates. This avoids a separate subtraction of ‘A’ and addition of 10.

    The following demo with PRTBYT and GETBYT illustrates how this could be done in a user program.

    0001   0000             ;
    0002   0000             ; GETBYTC with error checking
    0003   0000             ; illustrates shortcomings in PACK
    0004   0000             ; - G and ; and possibly more accepted without error
    0005   0000             ;
    0006   0000             ; Demo of program: 
    0007   0000             ; KIM
    0008   0000             ; 0000 00 200
    0009   0000             ; 0200 A9 G
    0010   0000             ; &gt;12=12
    0011   0000             ; &gt;33=33
    0012   0000             ; &gt;G?
    0013   0000             ; &gt;H?
    0014   0000             ; &gt;GG=00
    0015   0000             ; &gt;;;=BB
    0016   0000             ; &gt;AB=AB
    0017   0000             ; &gt;CD=CD
    0018   0000             ; &gt;EE=EE
    0019   0000             ; &gt;
    0020   0000             ;
    0021   0000             ; KIM-1 defines
    0022   0000             ;
    0023   0000             PACK 	= 	$1FAC		; pack hex character into INL, shift in
    0024   0000             PRTBYT	= 	$1E3B		; print byte as 2 hex characters
    0025   0000             GETCH	=	$1E5A		; receive character from TTY serial
    0026   0000             OUTCH	= 	$1EA0		; send character via TTY serial
    0027   0000             INL		= 	$F8	
    0028   0000             INH		= 	$F9
    0029   0000             ;
    0030   0200             	.org $0200
    0031   0200             
    0032   0200             ; demo code
    0033   0200             ;
    0034   0200 A9 00       LOOP 	LDA	#$00
    0035   0202 85 F8       		STA INL			; zero hex byte
    0036   0204 85 F9       		STA	INH
    0037   0206 20 3E 02    		JSR CRLF
    0038   0209 A9 3E       		LDA #&#039;&gt;&#039;		; prompt
    0039   020B 20 A0 1E    		JSR OUTCH
    0040   020E 20 28 02    		JSR GETBYTC
    0041   0211 90 08       		BCC OK
    0042   0213 A9 3F       		LDA #&#039;?&#039;		; error
    0043   0215 20 A0 1E    		JSR OUTCH
    0044   0218 4C 00 02    		JMP LOOP
    0045   021B             ;		
    0046   021B 48          OK		PHA
    0047   021C A9 3D       		LDA	#&#039;=&#039;
    0048   021E 20 A0 1E    		JSR OUTCH
    0049   0221 68          		PLA
    0050   0222 20 3B 1E    		JSR PRTBYT
    0051   0225 4C 00 02    		JMP LOOP		; repeat	
    0052   0228             ;
    0053   0228             ; subroutine GETBYTC
    0054   0228             ; read 2 hex characters from TTY input
    0055   0228             ; pack into one byte
    0056   0228             ; Returns: carry clear if hex OK, A == hex byte
    0057   0228             ; clobbers X and Y
    0058   0228             ;
    0059   0228             
    0060   0228             
    0061   0228 20 5A 1E    GETBYTC	JSR	GETCH		; read character
    0062   022B 20 AC 1F    		JSR	PACK		; pack into INL
    0063   022E D0 0C       		BNE     EGETB		; A = 0 if hex number
    0064   0230 20 5A 1E    		JSR	GETCH		; read second character
    0065   0233 20 AC 1F    		JSR	PACK		; pack into INL
    0066   0236 D0 04       		BNE     EGETB		; A = 0 if hex number
    0067   0238 A5 F8       		LDA	INL
    0068   023A 18          		CLC
    0069   023B 60          		RTS
    0070   023C 38          EGETB	        SEC
    0071   023D 60          		RTS
    0072   023E             		
    0073   023E A9 0D       CRLF	        LDA 	#$0D
    0074   0240 20 A0 1E    		JSR 	OUTCH
    0075   0243 A9 0A       		LDA 	#$0A
    0076   0245 20 A0 1E    		JSR		OUTCH 
    0077   0248 60          		RTS
    0078   0249             
    0079   0249             		.END
    0080   0249             		
    0081   0249             
    tasm: Number of errors = 0