O BASIC para armazenar número, normalmente armazena a parte ASCII seguida de 0x0E e uma representação numérica de 5 bytes, que é usada directamente pela rotina da calculadora de stack de vírgula flutuante do Spectrum.
Esta representação existe, para acelerar o interprete de BASIC. Aquando da edição ou LIST de uma linha BASIC, apenas se lida com a representação ASCII, mas fazendo ENTER para introdução a linha, esta é introduzida em RAM com a representação ASCII seguida de 0x0E mais a representação numérica.
Ou seja, em runtime, a representação ASCII é ignorada quando a representação numérica existe, e é usada a representação numérica para lidar com números. (excepção feita a um VAL "número").
Portanto, um número inteiro em 5 bytes menor que 65536, é representado por:
Exemplo: 45000 (AFC8)
00 00 C8 AF 00
Exemplo: 45000 (AFC8)
00 00 C8 AF 00
Note-se que o primeiro byte a $00 denota um inteiro, e o segundo byte a $FF um número negativo. No entanto, em listagens BASIC e variáveis, a ROM parece preferir usar o sinal - (ASCII $2D ) seguido da representação do número positiva.
Se em variáveis, apenas os 5 bytes são usados, em BASIC na prática são 6 bytes, já que a representação numérica é sempre precedida por 0x0E.
10 PRINT 45000 [int:45000,$AFC8]
5CCB 00 0A 0D 00 F5 34 35 30 30 30 0E 00 00 C8 AF 00 ....?45000...ȯ.
5CDB 0D
20 PRINT -5454 [int:5454,$154E]
5CDC 00 14 0D 00 F5 2D 35 34 35 34 0E 00 00 4E 15 00 ....?-5454...N..
5CEC 0D
30 PRINT VAL "50"
5CED 00 1E 07 00 F5 B0 22 35 30 22 0D ....??"50".
Zona de variáveis BASIC
Por exemplo, no Pheenix:
Exemplo:
Temos então a linha em RAM:
5CF7 61 00 00 28 00 00 (a=40)
Como método de protecção, pode-se alterar a representação numérica. No entanto, estas modificações perdem-se editando as linhas em questão. Estes artifícios eram usados em software comercial.
Por exemplo, no Pheenix:
- B
(PROG) 5CCB (VARS) 5DA0 (NXTLIN) 5DA0
1 CLEAR 24500
2 INK 0 : PAPER 0 : BORDER 0 :CLS
3 PRINT AT 8,7;"....PHEENIX is loading";AT 10,9;"........ Please Wait ......"
4 POKE 23659,0
[mem:$5D75]
5 LOAD ""CODE 24576[int:24532,$5FD4]
5D75 00 05 10 00 EF 22 22 AF 32 34 35 37 36 0E 00 00 ....?""?24576...
5D85 D4 5F 00 0D
[mem:$5D89]
6 LOAD ""CODE :RANDOMIZE USR 30121[int:30105,$7599]
5D89 00 06 13 00 EF 22 22 AF 3A F9 C0 33 30 31 32 31 ....?""?:??30121
5D99 0E 00 00 99 75 00 0D
Exemplo:
No programa, vamos adulterar o 0 para apontar para uma rotina RET em ROM (retornar ao BASIC em vez de fazer RESET).
10 PRINT USR 0
Temos então a linha em RAM:
5CCB 00 0A 0A 00 F5 C0 30 0E 00 00 00 00 00 0D
Que vamos alterar para apontar para $171D em vez de 0.
Para tal fazemos:
POKE 23765,29 ; $5CD5 = $1D
POKE 23766,23 ; $5CD6 = $17
Ficando:
[mem:$5CCB]
10 PRINT USR 0[int:5917,$171D]
Ou em RAM:
5CCB 00 0A 0A 00 F5 C0 30 0E 00 00 1D 17 00 0D
Parabéns Rui pelo excelente trabalho. Estou aqui recordando meus primeiros passos com o TK85, mas agora na linha Spectrum! SHOW! ;-)
ResponderEliminar