By default, your program will start on the page boundary immediately following the interpreter's data area and the 'dynamic data structures' will immediately follow your program. The total group of the dynamic data structures is called the 'heap'. The base of the program control stack is located at HIMEM.
As your program runs, the heap expands upwards towards the stack and the stack expands downwards towards the heap. If the two should meet, you get a 'No room' error. Fortunately, there is a limit to the amount by which the stack and the heap expand.
In general, the heap only expands whilst new variables are being declared. However, bad management of string variables can also cause the heap to expand.
In addition to running your program, the stack is also used 'internally' by the BBC BASIC (Z80) interpreter. Its size fluctuates but, in general, it expands every time you increase the depth of nesting of your program structure and every time you increase the number of local variables in use.
|
|
|
The function of HIMEM, LOMEM, TOP and PAGE are briefly discussed below. You will find more complete definitions elsewhere in this manual. You can directly set HIMEM, LOMEM and PAGE. However, for most of your programs you won't need to alter any of them. You will probably only need to change HIMEM if you want to put some machine code sub-routines at the top of memory.
HIMEM | The first address at the top of memory which is not available for use by BBC BASIC (Z80). The base of the program stack is set at HIMEM. (The first 'thing' stored on the stack goes at HIMEM-1.) |
LOMEM | The start address for the heap. The first of the dynamic data structures starts at LOMEM. |
TOP | The first free location after the end of your program. Unless
you have set LOMEM yourself, LOMEM=TOP.
You cannot directly set TOP. It alters as you enter
your program. The current length of your program is given by:
PRINT TOP-PAGE |
PAGE | The address of the start of your program. You can place several programs in memory and switch between them by using PAGE. Don't forget to control LOMEM as well. If you don't, the heap for one program might overwrite another program. |
Assigning a null string to stop$ prevents the space for the last entry in the array being recovered when it is emptied.10 DIM names$(10) 20 FOR i=0 TO 10 30 name$(i)=STRING$(20," ") 40 NEXT 50 stop$="" 60 FOR i=0 TO 10 70 name$(i)="" 80 NEXT
|
The first variable created for each starting character is accessed via the index and subsequently created variables are accessed via the index and the chain. Consequently, there is some speed advantage to be gained by arranging for all your variables to start with a different character. Unfortunately, this can lead to some pretty unreadable names and programs.
|
The smallest amount of space is taken up by a variable with a single letter name. The static integer variables, which are not included in the variable chains, use the names A% to Z%. Thus, the only single character names available for dynamic integer variables are a% to z% plus _% and `% (CHR$(96)). As shown below, integer variables with these names will occupy 8 bytes.
|
|
As with integer variables, variables with single character names occupy the least memory. (However, the names A to Z are available for dynamic real variables.) Whilst a real variable requires an extra byte to store the number, the '%' character is not needed in the name. Thus, integer and real variables with the same name occupy the same amount of memory. However, this does not hold for arrays, since the name is only stored once.
In the following examples, the bytes are shown in the more human-readable manner with the MSB on the left.
The value 5.5 would be stored as shown below.
Because the sign bit is assumed to be 1, this would become:
Mantissa Exponent .0011 0000 0000 0000 0000 0000 0000 0000 1000 0010 Sign Bit &30 00 00 00 &82
The equivalent in decimal is:
Mantissa Exponent .1011 0000 0000 0000 0000 0000 0000 0000 1000 0010 &B0 00 00 00 &82
(0.5+0.125+0.0625) * 2^(130-127)BBC BASIC (Z80) stores integer values in real variables in a special way which allows the faster integer arithmetic routines to be used if appropriate. The presence of an integer value in a real variable is indicated by the stored exponent being zero. Thus, if the stored exponent is zero, the real variable is being used to hold an integer and the 4 byte mantissa holds the number in normal integer format.
= 0.6875 * 2^3
= 0.6875 * 8
= 5.5
Depending on how it is put there, an integer value can be stored in a real variable in one of two ways. For example,
will set the exponent to zero and store the integer &00 00 00 05 in the mantissa. On the other hand,number=5
will set the exponent to &82 and the mantissa to &20 00 00 00.number=5.0
The two ways of storing an integer value are illustrated in the following four examples.
Example 1 | ||||||
number=5 | & 00 | 00 | 00 | 00 | 05 | Integer 5 |
Example 2 | ||||||
number=5.0 | & 82 | 20 | 00 | 00 | 00 | Real 5.0 |
This is treated as | ||||||
& 82 | A0 | 00 | 00 | 00 | ||
= = = |
(0.5+0.125)*2^(130-127) 0.625*8 5 | |||||
because the sign bit is assumed to be 1. | ||||||
Example 3 | ||||||
number=-5 | & 00 | FF | FF | FF | FB | |
The 2's complement gives | ||||||
& 00 | 00 | 00 | 00 | 05 | Integer -5 | |
Example 4 | ||||||
number=-5.0 | & 82 | A0 | 00 | 00 | 00 | Real -5.0 |
(The sign bit is already 1) | ||||||
= = Magnitude = |
(0.5+0.125)*2^(130-127) 0.625*8 5 |
If all this seems a little complicated, try using the program on the next page to accept a number from the keyboard and display the way it is stored in memory. The program displays the 4 bytes of the mantissa in 'human readable order' followed by the exponent byte. Look at what happens when you input first 5 and then 5.0 and you will see how this corresponds to the explanation given above. Then try -5 and -5.0 and then some other numbers. (The program is an example of the use of the byte indirection operator. See the Indirection section for details.)
The layout of the variable 'NMBR' in memory is shown below.
|
10 NUMBER=0 20 DIM A% -1 30 REPEAT 40 INPUT"NUMBER PLEASE "NUMBER 50 PRINT "& "; 60 : 70 REM Step through mantissa from MSB to LSB 80 FOR I%=2 TO 5 90 REM Look at value at address A%-I% 100 NUM$=STR$~(A%?-I%) 110 IF LEN(NUM$)=1 NUM$="0"+NUM$ 120 PRINT NUM$;" "; 130 NEXT 140 : 150 REM Look at exponent at address A%-1 160 N%=A%?-1 170 NUM$=STR$~(N%) 180 IF LEN(NUM$)=1 NUM$="0"+NUM$ 190 PRINT " & "+NUM$'' 200 UNTIL NUMBER=0
|
When a string variable is first created in memory, the characters of the string follow immediately after the two bytes containing the start address of the string and the current and maximum lengths are the same. While the current length of the string does not exceed its length when created, the characters of the string will follow the address bytes. When the string variable is set to a string which is longer than its original length, there will be insufficient room in the original position for the characters of the string. When this happens, the string will be placed on the top of the heap and the new start address will be loaded into the two address bytes. The original string space will remain, but it will be unusable. This unusable string space is called 'garbage'. See the Variables sub-section for ways to avoid creating garbage.
Because the original length and the current length of the string are each stored in a single byte in memory, the maximum length of a string held in a string variable is 255 characters.
would place &54 (T) at address &8000, &68 (h) at address &8001, etc. Because the string is placed at a predetermined location in memory it is called a 'fixed' string. Fixed strings are not included in the variable chains and they do not have the overheads associated with a string variable. However, since the length of the string is not stored, an explicit terminator (&0D) is used. Consequently, in the above example, byte &8010 would be set to &0D.$&8000="This is a string"
CONTENTS |
CONTINUE |