Page Last Altered:

**Submitted by Steve Fewell**

**Routine**:tokeniseLineNumber

**Name**: Tokenise Line Number

**Starting Address**: &8D04

**Entry criteria**: A contains the first digit of the line number.

Pointer (&37, &38) points to the address in the program of the first digit of the Program Line Number.

**Exit**: The line number in the Program Line is tokenised.

Carry flag is set if error occurred (Line number too large).

**Description**:

Store the 4 lowest bits (bits 0, 1, 2 & 3) of the first digit (in A) in location &3D.

Set X to zero (the upper digit of the 2-byte binary line number)
Set Y to 1 (so the next character read will be the character after the first digit of the line number).

[&8D0C] Read next character from the (&37, &38) pointer.

If the next character is not a digit then go to &8D42 to store the line number token and exit.

Store the 4 lowest bits (bits 0, 1, 2 & 3) of the new digit on the stack.

Store X in location &3E.

Multiply the Line Number (in locations &3D (LSB) abd &3E (MSB) by 10, by:

*1) Storing the value of location &3D and &3E.

*2) Multiplying the Line Number value (in locations &3D-&3E) by 4

*3) Adding the stored &3D and &3E value to the result from step *2).

*4) Multiplying the Line Number value (in locations &3D-&3E [note: actually A at this stage] by 2.

If the Line Number MSB (&3E) becomes negative (or overflows) at any time during this multiply operation, the routine

will be exited with Carry set (as the line number is too large).

Next, retrieve the encoded next digit value from the Stack and add this digit to the Line Number (&3D-&3E).

This adds the digit to the binary line number.

If X (working copy of &3E) is negative then jump to &8D3F (exit with carry flag set), as the line number is too large.

Otherwise, jump back to &8D0C to process any further digits.

&8D42 Store Line Number Token & exit:

Set A to #&8D (The Token for Line Number).

Call routine &8CEB to replace the ASCII Line Number currently present in the Program line with #&8D.

Next, Copy the program text pointer (&37, &38) to locations (&39 - &3A).

This is a pointer to the #&8D token value on the program line.

Increment Pointer (&37, &38) by 3 (to point to the location after the 3-byte tokenised line number.

by the 3-digit encoded line number value).

Copy program line text from location pointed to by (&39,&3A) to the (&37, &38) location (last byte first)

[routine &8CEB set Y to point to the end of the command line].

The first byte is correctly set to #&8D, so don't copy this byte.

This moves the command line text (after the program line number lcoation) along 3 bytes - to make space for the

tokenised line number.

Set Y to 3 (deal with the last byte of the tokenised line Number first).

Set A to X (the MSB of the Line Number).

OR A value with #&40 (01000000) to set bit 6 of the Byte, then store this result in the 3rd byte of the

tokenised line number (i.e. the 3rd byte after the #&8D token value).

Set A to &3D value (LSB of Line Number). AND this value with #&3F (00111111) to clear the top 2 bits of

the value and OR with #&40 (01000000) to set bit 6. Finally, store the result in the 2nd byte of the Tokenised

Line number (i.e. the 2nd byte after the #&8D token value).

Next, clear all but the top two bits of the &3D (LSB of Line Number) value.

AND the MSB of the Line Number with #&C0 (11000000) to clear all but the top 2 bits. Shift the top two bits

of the MSB Line Number value along 2 positions and set the top 2 bits to the top two bits of the &3D (LSB of Line

Number) value. EOR this result with #&54 (01010100).

Store the result as the 1st byte of the tokenised Line Number.

The resulting tokenised value contains 3 bytes which each contain an encoded value between &40 and &7F.

This ensures that tokenised Line Numbers cannot be confused with BASIC tokenised keyword values (which are all >= &80),

or with the quote character (").

This is important, otherwise BASIC might interpret the Line Number value as a String or as another BASIC keyword.

**Examples**:

Example1: Line Number = 10

[&8D04] A=&31. AND #&0F with A (1st digit), result=&01 (store in &3D).

[&8D14] A=&30. AND #&0F with A (2nd digit), result=&00. &3E & X = &00.

[&8D1E] Now: A=&02 and &3E=&00.

[&8D23] Now: A=&04 and &3E=&00.

[&8D27] Now: &3D and A = &05
[&8D2E] Now: A=&00, after addition, A=&00. &3D=&0A, A=&00.

[&8D39] Now: X=&00, A=&00 and &3D=&0A.

This 2-byte value is tokenised as follows:

(X = &00, &3D = &0A)

3rd byte of tokenised value = &40 (X (&00) OR &40).

2nd byte of tokenised value = &4A (A (&0A) OR &40).

1st byte of tokenised value = &54 (&00 EOR &54).

Example2: Line Number = 12345

[&8D04] A=&31. AND #&0F with A (1st digit), result=&01 (store in &3D).

[&8D14] A=&32. AND #&0F with A (2nd digit), result=&02. &3E & X = &00.

[&8D1E] Now: A=&02 and &3E=&00.

[&8D27] Now: A = &04, &3E = &00 and &3D = &05.
[&8D2E] Now: A=&00, after addition, A=&00. &3D=&0A, A=&00.

[&8D39] Now: X=&00, A=&0C and &3D=&0C.

[&8D14] A=&33. AND #&0F with A (3rd digit), result=&03. &3E & X = &00.

[&8D1E] Now: A=&0C (= &18 after addition) and &3E=&00.

[&8D27] Now: A = &30, &3E = &00 and &3D = &3C.
[&8D2E] Now: A=&00, after addition, A=&00. &3D=&78, A=&00.

[&8D39] Now: X=&00, &3D=&7B.

[&8D14] A=&34. AND #&0F with A (4th digit), result=&04. &3E & X = &00.

[&8D1E] Now: A=&7B (= &F6 after addition) and &3E=&00.

[&8D27] Now: A = &EC, &3E = &01 and &3D = &67.
[&8D2E] Now: A=&00, after addition, A=&02. &3D=&CE, A=&04.

[&8D39] Now: X=&04 and &3D=&D2.

[&8D14] A=&35. AND #&0F with A (5th digit), result=&05. &3E & X = &04.

[&8D1E] Now: A=&D2 (= &A4 after addition) and &3E=&09.

[&8D27] Now: A = &48, &3E = &13 and &3D = &1A.
[&8D2E] Now: A=&04, after addition, A=&18. &3D=&34, A=&30.

[&8D39] Now: X=&30 and &3D=&39.

This 2-byte value is tokenised as follows:

(X = &30, &3D = &39)

3rd byte of tokenised value = &70 (X (&40) OR &30).

2nd byte of tokenised value = &79 (A (&40) OR &39).

1st byte of tokenised value = &54 (&00 EOR &54).

Example3: Line Number = 333

[&8D04] A=&33. AND #&0F with A (1st digit), result=&03 (store in &3D).

[&8D14] A=&33. AND #&0F with A (2nd digit), result=&03. &3E & X = &00.

[&8D1E] Now: A=&06 and &3E=&00.

[&8D27] Now: A = &0C, &3E = &00 and &3D = &0F.
[&8D2E] Now: A=&00, after addition, A=&00. &3D=&1E, A=&00.

[&8D39] Now: X=&00 and &3D=&21.

[&8D14] A=&33. AND #&0F with A (3rd digit), result=&03. &3E & X = &00.

[&8D1E] Now: A=&42 and &3E=&00.

[&8D27] Now: A = &84, &3E = &00 and &3D = &A5.
[&8D2E] Now: A=&00, after addition, A=&00. &3D=&4A, A=&01.

[&8D39] Now: X=&01 and &3D=&4D.

This 2-byte value is tokenised as follows:

(X = &01, &3D = &4D)

3rd byte of tokenised value = &41 (X (&01) OR &40).

2nd byte of tokenised value = &4D (A (&0D) OR &40).

1st byte of tokenised value = &44 (&10 EOR &54) [(A (&01) AND &C0 => &00) ORA &3D (top 2 bits) = &40;

divide by 4 = &10 EOR &54 ==> &44].

8D04 | ) | 041 015 | 29 0F | AND#&0F |

8D06 | = | 133 061 | 85 3D | STA &3D |

8D08 | 162 000 | A2 00 | LDX#&00 | |

8D0A | 160 000 | A0 00 | LDY#&00 | |

8D0C | 200 | C8 | INY | |

8D0D | 7 | 177 055 | B1 37 | LDA (&37),Y |

8D0F | 032 148 141 | 20 94 8D | JSR &8D94 Check for numeric digit | |

8D12 | . | 144 046 | 90 2E | BCC 46 --> &8D42 (no more numeric digits present) |

8D14 | ) | 041 015 | 29 0F | AND#&0F |

8D16 | H | 072 | 48 | PHA |

8D17 | > | 134 062 | 86 3E | STX &3E |

8D19 | = | 165 061 | A5 3D | LDA &3D |

8D1B | 010 | 0A | ASL A | |

8D1C | &> | 038 062 | 26 3E | ROL &3E |

8D1E | 0 | 048 031 | 30 1F | BMI 31 --> &8D3F |

8D20 | 010 | 0A | ASL A | |

8D21 | &> | 038 062 | 26 3E | ROL &3E |

8D23 | 0 | 048 026 | 30 1A | BMI 26 --> &8D3F |

8D25 | e= | 101 061 | 65 3D | ADC &3D |

8D27 | = | 133 061 | 85 3D | STA &3D |

8D29 | 138 | 8A | TXA | |

8D2A | e> | 101 062 | 65 3E | ADC &3E |

8D2C | = | 006 061 | 06 3D | ASL &3D |

8D2E | * | 042 | 2A | ROL A |

8D2F | 0 | 048 014 | 30 0E | BMI 14 --> &8D3F |

8D31 | 176 012 | B0 0C | BCS 12 --> &8D3F | |

8D33 | 170 | AA | TAX | |

8D34 | h | 104 | 68 | PLA |

8D35 | e= | 101 061 | 65 3D | ADC &3D |

8D37 | = | 133 061 | 85 3D | STA &3D |

8D39 | 144 209 | 90 D1 | BCC -47 --> &8D0C | |

8D3B | 232 | E8 | INX | |

8D3C | 016 206 | 10 CE | BPL -50 --> &8D0C | |

8D3E | H | 072 | 48 | PHA |

8D3F | h | 104 | 68 | PLA |

8D40 | 8 | 056 | 38 | SEC |

8D41 | ` | 096 | 60 | RTS |

8D42 | 136 | 88 | DEY | |

8D43 | 169 141 | A9 8D | LDA#&8D | |

8D45 | 032 235 140 | 20 EB 8C | JSR &8CEB Replace untokenised value with token | |

8D48 | 7 | 165 055 | A5 37 | LDA &37 |

8D4A | 9 | 133 057 | 85 39 | STA &39 |

8D4C | 8 | 165 056 | A5 38 | LDA &38 |

8D4E | : | 133 058 | 85 3A | STA &3A |

8D50 | 032 162 141 | 20 A2 8D | JSR &8DA2 Increment Pointer (&37, &38) | |

8D53 | 032 162 141 | 20 A2 8D | JSR &8DA2 Increment Pointer (&37, &38) | |

8D56 | 032 162 141 | 20 A2 8D | JSR &8DA2 Increment Pointer (&37, &38) | |

8D59 | 9 | 177 057 | B1 39 | LDA (&39),Y |

8D5B | 7 | 145 055 | 91 37 | STA (&37),Y |

8D5D | 136 | 88 | DEY | |

8D5E | 208 249 | D0 F9 | BNE -7 --> &8D59 | |

8D60 | 160 003 | A0 03 | LDY#&03 | |

8D62 | 138 | 8A | TXA | |

8D63 | @ | 009 064 | 09 40 | ORA#&40 |

8D65 | 9 | 145 057 | 91 39 | STA (&39),Y |

8D67 | 136 | 88 | DEY | |

8D68 | = | 165 061 | A5 3D | LDA &3D |

8D6A | )? | 041 063 | 29 3F | AND#&3F |

8D6C | @ | 009 064 | 09 40 | ORA#&40 |

8D6E | 9 | 145 057 | 91 39 | STA (&39),Y |

8D70 | 136 | 88 | DEY | |

8D71 | ? | 169 063 | A9 3F | LDA#&3F |

8D73 | = | 020 061 | 14 3D | TRB &3D |

8D75 | 138 | 8A | TXA | |

8D76 | ) | 041 192 | 29 C0 | AND#&C0 |

8D78 | J | 074 | 4A | LSR A |

8D79 | J | 074 | 4A | LSR A |

8D7A | = | 005 061 | 05 3D | ORA &3D |

8D7C | J | 074 | 4A | LSR A |

8D7D | J | 074 | 4A | LSR A |

8D7E | IT | 073 084 | 49 54 | EOR#&54 |

8D80 | 9 | 145 057 | 91 39 | STA (&39),Y |

8D82 | 024 | 18 | CLC | |

8D83 | ` | 096 | 60 | RTS |