Now that I’ve been successful in printing strings in whole and character by character, I thought the next logical step would be to get a string from the user. This post deals specifically with that. I use the CIO routine Get Record ($05) to accomplish it. I also introduce a new instruction. Let’s get to it.
Instructions
I only introduce one new instruction this time. It is:
- DEY – DEcrement the Y register. This reduces the value in the Y register by 1.
Source Code
10 *= $3600 20 PRSPTR = $CB 21 INSPTR = $CD 39 ; Defines 70 CIOV = $E456 71 ICHID = $0340 ;IOCB 0 S: 72 ICCOM = $0342 ;IOCB Command 73 ICBAL = $0344 ;Xfer Buffer Adr 74 ICBAH = $0345 75 ICBLL = $0348 ;Buffer Len 76 ICBLH = $0349 77 ROWCRS = 84 78 COLCRS = 85 80 EOL = $9B 81 EOS = $00 82 CLS = $7D 300 ; Test printing 302 TEST 310 LDA #SCLR/256 312 LDX #SCLR&255 314 JSR PRTCH 320 LDX #0 322 LDY #0 324 JSR CURXY 326 LDA #SRULE/256 328 LDX #SRULE&255 330 JSR PRTCH 340 LDX #0 350 LDY #2 360 JSR CURXY 370 LDA #SP1/256 380 LDX #SP1&255 390 JSR PRTCH 430 LDA #VSNAME/256 440 LDX #VSNAME&255 450 JSR INPSTR 460 LDX #0 470 LDY #4 480 JSR CURXY 490 LDA #SP2/256 500 LDX #SP2&255 510 JSR PRTCH 520 LDA #VSNAME/256 530 LDX #VSNAME&255 540 JSR PRTCH 550 LDA #SWELC/256 560 LDX #SWELC&255 570 JSR PRTCH 580 RTS 5000 ; Print Subroutine 5005 PRTCH 5010 ; Store Starting String Address 5015 STX PRSPTR 5020 STA PRSPTR+1 5030 LDA #$00 5040 STA PRINDX 5050 ; Set IOCB Command 5052 LDX #$00 5055 LDA #$0B 5060 STA ICCOM,X 5070 ; Set Max Buffer Length 5072 LDA #$00 5080 STA ICBLL,X 5090 STA ICBLH,X 5100 ; Call CIO to Print 5105 PRCHLP LDY PRINDX 5108 LDA (PRSPTR),Y 5115 BEQ PRCHDN 5116 JSR CIOV 5120 INC PRINDX 5130 BNE PRCHLP 5140 PRCHDN RTS 6000 ; Position Subroutine 6005 CURXY 6010 STX COLCRS 6020 STY ROWCRS 6030 RTS 7000 ; Input String 7005 INPSTR 7010 ; Store Starting String Address 7015 STX ICBAL 7020 STA ICBAH 7050 ; Set IOCB Command 7052 LDX #$00 7055 LDA #$05 ; Get Record 7060 STA ICCOM,X 7070 ; Set Max Buffer Length 7072 LDA #30 7080 STA ICBLL,X 7085 LDA #0 7090 STA ICBLH,X 7100 ; Call CIO to Input 7110 JSR CIOV 7160 RTS 10000 ; String Data 10001 SCLR .BYTE CLS 10002 SRULE .BYTE "012345678901234567890123456789012345",EOS 10005 SP1 .BYTE "Name? ",EOS 10010 SP2 .BYTE "Hello ",EOS 10020 SWELC .BYTE ", Welcome!",EOS 10050 VSNAME *= *+30 10060 PRINDX *= *+1 15000 .END
Breakdown
As usual I am only going to document what is different.
- Lines 310 to 390: Clear the screen, print the ruler, print the input prompt “Name? “.
- Lines 430 to 450: Load the Accumulator and X register with the high and low bytes of the input string address, then call the input subroutine identified by label INPSTR.
- Lines 460 to 570: Print the “Hello ” message, followed by the input string, followed by “, Welcome!”.
- Line 580: Return (end of program)
- Lines 5000 to 5140: The print string routine that prints character by character rather than the whole string as previously written about.
- Lines 6000 to 6030: The cursor positioning routine as previously written about.
- Line 7005: Start of the input string sub routine, labelled with INPSTR.
- Line 7015 to 7020: Store the string address high and lowe bytes into ICBAL and ICBAH (the IOCB string address).
- Line 7052: Load the X register with 0 to reflect IOCB 0.
- Line 7055: Load the Accumulator with 5, the IOCB command for get record.
- Line 7060: Store the Accumulator in the IOCB’s command address.
- Line 7072: Load the Accumulator with 30. This is the maximum number of characters that will be accepted.
- Line 7080: Store the Accumulator in the IOCB’s buffer length low byte address (ICBLL).
- Line 7085: Load the Accumulator with 0. This only needs to be defined if the maximum string length is greater than 255.
- Line 7090: Store the Accumulator in the IOCB’s buffer length high byte address (ICBLH).
- Line 7110: Call the CIO routine to get the input.
- Line 7160: Return from the subroutine.
- Line 10050: This is the input string address. Reserving 30 bytes.
- Line 10060: This is the print character index. Reserving 1 byte. I moved it from the beginning of the code to the end.
Assembly
After it is assembled and run, the program asks for your name. Enter a name and it is echo’d back with a welcome message:
Output and EOL Problem
As you can see from the output below there is a slight problem. When the user terminates the input with the Return key, EOL (155 / $9B) is added to the end of the string. So when it prints, an unexpected result is the cursor is moved to left most column on next row causing the next thing printed to be in the wrong location:
Since this is not desirable I had to revise the input routine slightly. After the input call, I load the Y register with the value in ICBLL, which is the number of characters actually input. Because the count includes the Return key, I decrement the value, then store and EOS (0) at the string address offset by the Y register value. This is a pointer operation so I needed another 2 bytes in page zero to store the address. I chose $CD.
Source Code – Revised
In the above listing, the highlighted lines reflect updates to the first source code listing.
10 *= $3600 20 PRSPTR = $CB 21 INSPTR = $CD 39 ; Defines 70 CIOV = $E456 71 ICHID = $0340 ;IOCB 0 S: 72 ICCOM = $0342 ;IOCB Command 73 ICBAL = $0344 ;Xfer Buffer Adr 74 ICBAH = $0345 75 ICBLL = $0348 ;Buffer Len 76 ICBLH = $0349 77 ROWCRS = 84 78 COLCRS = 85 80 EOL = $9B 81 EOS = $00 82 CLS = $7D 300 ; Test printing 302 TEST 310 LDA #SCLR/256 312 LDX #SCLR&255 314 JSR PRTCH 320 LDX #0 322 LDY #0 324 JSR CURXY 326 LDA #SRULE/256 328 LDX #SRULE&255 330 JSR PRTCH 340 LDX #0 350 LDY #2 360 JSR CURXY 370 LDA #SP1/256 380 LDX #SP1&255 390 JSR PRTCH 430 LDA #VSNAME/256 440 LDX #VSNAME&255 450 JSR INPSTR 460 LDX #0 470 LDY #4 480 JSR CURXY 490 LDA #SP2/256 500 LDX #SP2&255 510 JSR PRTCH 520 LDA #VSNAME/256 530 LDX #VSNAME&255 540 JSR PRTCH 550 LDA #SWELC/256 560 LDX #SWELC&255 570 JSR PRTCH 580 RTS 5000 ; Print Subroutine 5005 PRTCH 5010 ; Store Starting String Address 5015 STX PRSPTR 5020 STA PRSPTR+1 5030 LDA #$00 5040 STA PRINDX 5050 ; Set IOCB Command 5052 LDX #$00 5055 LDA #$0B 5060 STA ICCOM,X 5070 ; Set Max Buffer Length 5072 LDA #$00 5080 STA ICBLL,X 5090 STA ICBLH,X 5100 ; Call CIO to Print 5105 PRCHLP LDY PRINDX 5108 LDA (PRSPTR),Y 5115 BEQ PRCHDN 5116 JSR CIOV 5120 INC PRINDX 5130 BNE PRCHLP 5140 PRCHDN RTS 6000 ; Position Subroutine 6005 CURXY 6010 STX COLCRS 6020 STY ROWCRS 6030 RTS 7000 ; Input String 7005 INPSTR 7010 ; Store Starting String Address 7015 STX ICBAL 7020 STA ICBAH 7030 ; Store Str Address in P0 Ptr 7035 STX INSPTR 7040 STA INSPTR+1 7050 ; Set IOCB Command 7052 LDX #$00 7055 LDA #$05 ; Get Record 7060 STA ICCOM,X 7070 ; Set Max Buffer Length 7072 LDA #30 7080 STA ICBLL,X 7085 LDA #0 7090 STA ICBLH,X 7100 ; Call CIO to Input 7110 JSR CIOV 7115 ; Get # chars input 7120 LDY ICBLL 7130 ; Reduce char count by 1 7135 DEY 7140 ; Store EOS at EOL position 7145 LDA #EOS 7150 STA (INSPTR),Y 7160 RTS 10000 ; String Data 10001 SCLR .BYTE CLS 10002 SRULE .BYTE "012345678901234567890123456789012345",EOS 10005 SP1 .BYTE "Name? ",EOS 10010 SP2 .BYTE "Hello ",EOS 10020 SWELC .BYTE ", Welcome!",EOS 10050 VSNAME *= *+30 10060 PRINDX *= *+1 15000 .END
Breakdown
- Line 21: Sets the location for the INput String PoinTeR labelled as INSPTR to page zero address $CD.
- Line 7035 to 7040: Store the string address in the pointer location INSPTR.
- Line 7120: Load the Y register with the value in ICBLL. ICBLL holds the actual number of characters input after the CIO call completes.
- Line 7135: Decrement the Y register. The number of characters input includes the return key which I don’t want.
- Line 7145: Load the Accumulator with EOS (0).
- Line 7150: Store the value in the Accumulator in the input string address offset by the Y register. This will be the location of the Return (EOL / $9B). This basically turns the EOL into EOS. It uses indirect indexed addressing to get the actual string address stored in the location referenced (a pointer).
Final Assembly
After assembling the program with the changes above, running it produces the correct results.
First input your name, then it prints its back with a welcome message – correctly:
Another success! Hrm, what to do next…
Pingback: 6502, Including Others | Unfinished Bitness
Pingback: 6502, String Input Redux | Unfinished Bitness