- El número 0 ocupa en realidad 7 bytes (1 del 0, 1 del separador y 5 de su representación en coma flotante).
- El número 32767 ocupa en realidad 11 bytes (5 de la cadena, 1 del separador y otros 5 de la coma flotante).
- Si hay una discrepancia de números, se utiliza el de la coma flotante. Es decir, si ves un USR 32767 y en la representación de coma flotante pone 30000, el programa saltará a la dirección 30000. Esto lo he visto en algún cargador para despistar a hackers.
Si se usan expresiones en lugar de números, el número nos va a ocupar en memoria el mismo espacio que la expresión (salvo que la expresión contenga números). Así que esta es una tabla de sustituciones que pueden servir para ahorrar memoria y espacio:
Código: Seleccionar todo
-1 = COS PI --> 2 bytes, se ahorran 5
0 = NOT PI --> 2 bytes, se ahorran 5
1 = SGN PI --> 2 bytes, se ahorran 5
3 = INT PI --> 2 bytes, se ahorran 5
x = VAL "x" --> siempre se ahorran 3 bytes
40000 = VAL "4e4" --> 6 bytes, se ahorran 5
En general, usar VAL ahorra tres bytes, salvo en el último caso en que utilizamos notación científica para "acortar" el número y nos ahorramos algún byte más.
Todo esto no es gratis y cada expresión debe ser evaluada (excepción debajo), por lo que lo que ahorramos en memoria lo pagamos en tiempo de proceso. En un cargador tenemos montones de tiempo, pero en el bucle principal de un juego en BASIC no. Hay que estudiar hasta que punto nos beneficia o nos perjudica usar esto.
Otro truco es que si vas a utilizar muchas veces un número, lo asignes a una variable de una sola letra. A partir de cierto límite, empiezas a ahorrar memoria. Además, si pones algo del estilo LET Z=NOT PI, la expresión sólo será evaluada una vez (cuando metes el valor a la variable) por lo que no penaliza demasiado la velocidad.
Ahora las preguntas...
- En esta tabla hay un montón de "huecos". Estaría bien disponer de los valores del 0 al 9 codificados en uno o dos bytes. Me interesarían sobre todo los valores del 0 al 7.
- El calculador. Esta parte que convierte las expresiones de BASIC a valores, a veces tiene un comportamiento no demasiado intuitivo. El calculador usa la pila, y si detecta que la pila va a colisionar con las variables, nos suelta un "Out of Memory". Esto hace que cuando vas muy pillado de memoria, a veces sea mejor dejar un USR 32767 funcione y un USR VAL "32767" no lo haga (aunque en teoría el último ocupe menos memoria). ¿Existe alguna regla para preveer el uso de memoria del calculador?
EDITO: Dos pifias (es lo que tiene escribir de memoria). Por una parte, me había olvidado por completo del byte que se usa como separador.
Por otra parte, usar BIN en vez de 0 no ahorra ningún byte (he corregido la tabla para arreglarlo). La clave es que BIN se trata como si fuera BIN 0, y se codifica como un BIN con un "cero numérico" detrás... lo que no ahorra bytes. La representación de estos números sería así:
Código: Seleccionar todo
0 - 0x30 0x0E 0x00 0x00 0x00 0x00 0x00 - 7 bytes
BIN - 0xC4 0x0E 0x00 0x00 0x00 0x00 0x00 - 7 bytes
VAL "0" - 0xB0 0x22 0x30 0x22 - 4 bytes
NOT PI - 0xC3 0xA7 - 2 bytes
Y nos quedamos con que la codificación más eficiente del cero parece ser NOT PI (la tradicional, vamos).