Page 1 of 1

Basic VAL function

Posted: Thu May 24, 2018 10:16 am
by tsm
Hello!
If I'm not mistaken, the VAL function takes a string containing an expression and returns a number which represents the result of the expression.
I'm reading a Basic listing and I found some constructs that confuse me a little. Some examples:

LET d=VAL "256"
GO SUB VAL "900"
POKE VAL "23658",VAL "8"

Why not simply:

LET d=256
GO SUB 900
POKE 23658,8

:?: :?: :?:

Thank you!

Re: Basic VAL function

Posted: Thu May 24, 2018 10:48 am
by djnzx48
In this case VAL's probably being used to save memory. Numbers on the Spectrum are stored with a 5-byte numeric representation accompanying the textual representation, which speeds up the interpreter as it doesn't have to parse each number every time it reads it. The downside is this ends up wasting memory. Although VAL looks like it's making the program larger, it actually saves bytes in most cases: you have three extra bytes for the VAL and the two quote marks, but you no longer have to store the 5-byte number and so you save two bytes overall.

There are also some other tricks you can do, such as BIN for zero, SGN PI for one, and INT PI for 3, but VAL is more general and works in most situations.

Hope this helps!

Re: Basic VAL function

Posted: Thu May 24, 2018 11:07 am
by RMartins
It's to save memory, since in BASIC representation, VAL "256", takes less bytes to represent the number 256 directly.

This saves memory, if you are really tight on it, but it's slower. So it's a compromise, that can be used on code that does not run often, or is just part of the loader for example.

The less bytes you consume in basic, the more bytes you can LOAD "" CODE, for assembly, for example.

Re: Basic VAL function

Posted: Thu May 24, 2018 11:13 am
by tsm
Got it, thank you!

Re: Basic VAL function

Posted: Thu May 24, 2018 11:16 am
by R-Tape
I think this is done more from habit than necessity. VAL and NOT PI are commonly used in short loaders for machine code games where the handful of bytes it saves doesn't make any difference, but then if you can save a few bytes then why not.

Actually how many bytes does NOT PI save?

Re: Basic VAL function

Posted: Thu May 24, 2018 11:48 am
by Ast A. Moore
R-Tape wrote: Thu May 24, 2018 11:16 am Actually how many bytes does NOT PI save?
Four.

Re: Basic VAL function

Posted: Thu May 24, 2018 2:23 pm
by spectron
The above is all relevant and correct but it was especially useful in Sinclair Basic on the unexpanded ZX81.

With only 1K for screen and program, every byte was even more important than on the Spectrum.

It may have been that it became habit and as mentioned, if you can save bytes then why not?

Re: Basic VAL function

Posted: Thu May 24, 2018 2:39 pm
by Einar Saukas
Ast A. Moore wrote: Thu May 24, 2018 11:48 am
R-Tape wrote: Thu May 24, 2018 11:16 am Actually how many bytes does NOT PI save?
Four.
Actually five :)

Re: Basic VAL function

Posted: Thu May 24, 2018 3:07 pm
by Ast A. Moore
Einar Saukas wrote: Thu May 24, 2018 2:39 pm
Ast A. Moore wrote: Thu May 24, 2018 11:48 am Four.
Actually five :)
Mmm . . . A zero is one byte, plus 5 bytes of the BASIC’s number representation. That’s six bytes. NOT PI is two bytes. Six minus two is four.

Re: Basic VAL function

Posted: Thu May 24, 2018 3:15 pm
by Einar Saukas
Ast A. Moore wrote: Thu May 24, 2018 3:07 pm
Einar Saukas wrote: Thu May 24, 2018 2:39 pm Actually five :)
Mmm . . . A zero is one byte, plus 5 bytes of the BASIC’s number representation. That’s six bytes. NOT PI is two bytes. Six minus two is four.
Plus one byte for control code 14 that prefixes the number representation IIRC.

Re: Basic VAL function

Posted: Thu May 24, 2018 3:16 pm
by Einar Saukas
spectron wrote: Thu May 24, 2018 2:23 pm The above is all relevant and correct but it was especially useful in Sinclair Basic on the unexpanded ZX81.

With only 1K for screen and program, every byte was even more important than on the Spectrum.
Text adventures in Sinclair BASIC usually need this trick to fit in 16K.

This is also useful for small tape loaders. Making them smaller allows setting RAMTOP to a lower address, so you can have more available space to load a code block.

Re: Basic VAL function

Posted: Thu May 24, 2018 4:19 pm
by R-Tape
Good job black works well with every other colour. I wonder if any games chose a Magenta colour scheme purely because they used BORDER PI on loading...

Re: Basic VAL function

Posted: Thu May 24, 2018 4:41 pm
by Kweepa
It's really a bizarre choice for a 1k machine's basic.
I guess the ZX80 BASIC, being integer only, didn't do this?
Microsoft BASIC leaves this kind of optimization in your hands - put the constant in a variable if it's in a tight loop.

Re: Basic VAL function

Posted: Thu May 24, 2018 7:13 pm
by Ast A. Moore
Einar Saukas wrote: Thu May 24, 2018 3:15 pm
Ast A. Moore wrote: Thu May 24, 2018 3:07 pm Mmm . . . A zero is one byte, plus 5 bytes of the BASIC’s number representation. That’s six bytes. NOT PI is two bytes. Six minus two is four.
Plus one byte for control code 14 that prefixes the number representation IIRC.
D’oh. Right you are!

Re: Basic VAL function

Posted: Fri May 25, 2018 8:46 am
by djnzx48
Hmm, it looks like I was mistaken about BIN using fewer bytes. I just checked the memory of a BASIC program and it turns out that even if you have no digits after the BIN, it still uses 5 extra bytes to store the value and so uses exactly the same amount of memory as the number 0.

Re: Basic VAL function

Posted: Fri May 25, 2018 11:16 am
by Ast A. Moore
djnzx48 wrote: Fri May 25, 2018 8:46 am Hmm, it looks like I was mistaken about BIN using fewer bytes. I just checked the memory of a BASIC program and it turns out that even if you have no digits after the BIN, it still uses 5 extra bytes to store the value and so uses exactly the same amount of memory as the number 0.
Yes, NOT PI is the way to go. Honestly, when it comes to loaders, I prefer using machine code inside BASIC.

Re: Basic VAL function

Posted: Sun May 27, 2018 4:04 am
by djnzx48
You'd have to make sure that the loader is relocatable though, as I'm pretty sure peripherals like the Interface 1 can move BASIC up in memory to make room for their own data.

Another alternative is to find some empty space on the loading screen and stick the loader there. If you go this route, you also get the advantage that it's a lot easier to load into the entire memory without having to worry about what happens when the loader gets overwritten.

Re: Basic VAL function

Posted: Sun May 27, 2018 9:51 am
by Ast A. Moore
djnzx48 wrote: Sun May 27, 2018 4:04 am You'd have to make sure that the loader is relocatable though.
Sure. That’s trivial, though, particularly if you’re using a ROM-based loader. A custom loader would have to be relocated to non-contended memory anyway, so if you’re using calls within it, the addresses must be pre-calculated in relation to the execution location. Incidentally, I use both a ROM-based and a custom turbo loader in Yankee. Enable, say, Interface 1 in your emulator, initialize it by typing CAT 1 in BASIC, and then load each version of the game. They’ll both work. ;)

Re: Basic VAL function

Posted: Sat Jun 02, 2018 3:53 pm
by Pobulous
I liked the trick of putting all the numbers in as zero and poking the correct values into the 5 bytes so you'd end up with loader programs like:

10 CLEAR 0: POKE 0,0: LOAD "" CODE: RANDOMIZE USR 0

You would still save some memory on the larger numbers, plus it would add some simple obfuscation. Also if the line was edited it would now no longer work as the zeros would really be zeros.

Re: Basic VAL function

Posted: Thu Nov 04, 2021 12:34 pm
by +3code
Necroposting, sorry.

While exploring old utilities, I've found this:

https://spectrumcomputing.co.uk/entry/2 ... Cruncher_2

It's a good alternative to VAL for numbers >4 digits, saving more memory but maintaining the speed.