Managing memory on an Apple II using Applesoft BASIC can be quite complicated, especially for large programs.
A general map of Apple II memory at power-up looks like this:
$E000-FFFF - Monitor ROM / Extended RAM 8 / 8 kB
$D000-DFFF - BASIC ROM / RAM bank 1 & 2 4 / 4 / 4 kB
$C800-CFFF - Shared slot ROM memory 2 kB
$C100-C7FF - Permanent Slot ROM memory 256 per slot
$C000-C0FF - Softswitches 256 bytes
$6000-BFFF - Free memory 24 kB
$4000-5FFF - Free memory / Hi-Res page 2 8 kB
$2000-3FFF - Free memory / Hi-Res page 1 8 kB
$0C00-1FFF - Free memory 5 kB
$0800-0BFF - Free memory / Text page 2 1 kB
$0400-07FF - Text page 1 1 kB
$03D0-03FF - Interrupt vectors 48 bytes
$0300-03CF - Free memory 208 bytes
$0200-02FF - Input prompt character buffer 256 bytes
$0100-01FF - CPU stack 256 bytes
$0000-00FF - Zero page 256 bytes
When DOS 3.3 boots, it loads itself as high as possible in memory, just below $C000, and normally occupies $9600 to $BFFF, with 3 file buffers each 595 bytes long.
$9600-BFFF - DOS 3.3 and 3 file buffers 10.5 kB
$6000-95FF - Free memory 13.5 kB
If the number of buffers is reduced to 1, using the DOS command MAXFILES 1 then DOS occupies $9AA6 to $BFFF.
Applesoft BASIC programs normally load starting at $801, overlapping text page 2. BASIC programs load linearly into memory, and they cannot "jump over" memory regions.
As a BASIC program grows past 6 kilobytes in length ($0800 to $1FFF), it starts to cross into hi-res graphics page 1 followed by hi-res page 2. If you do anything with hi-res page 1 in this situation, you will damage or delete the end of your program.
When a BASIC program runs, it normally uses variables to store numbers and strings. These are stored in two separate groups, with the number values being placed immediately after the end of the program and growing upward, and the strings placed high in memory below DOS and growing downward.
So, over time as a BASIC program runs, both graphics pages are at risk of being overwritten with variable data, from above and below.
Also, if you were to write an assembly language program and store it at $6000, it is also at risk of eventually being overwritten by variables as a BASIC program continues to run.
Normally the variable and string use will grow indefinitely until the two come together. Then BASIC will perform what is called garbage collection, scanning through variable memory and removing unused old values and recovering free space. Garbage collection can be quite slow, if left to happen on its own in one huge process.
You can force BASIC to do variable garbage collection immediately by using the command PRINT FRE(0), which both returns a value reporting free memory for variables, and also runs garbage collection.
Using this command frequently in large programs will keep variable usage from growing too large, as well as preventing garbage collection from becoming too slow when it does happen.
In ProDOS, there is a DOS command FRE which is much faster than the FRE(0) built into Applesoft BASIC. This is used with the command PRINT CHR$(4)"FRE"
It is possible to control where BASIC stores variables using the commands HIMEM: and LOMEM: ... these are odd commands in that the colon is part of the command name.
LOMEM: is automatically adjusted by BASIC to point to the memory just after the end of a BASIC program. To obtain the current value, use: PRINT PEEK(74) + 256 * PEEK(75)
HIMEM: is automatically adjusted by DOS to point to just before the beginning of DOS. To obtain the current value, use: PRINT PEEK(76) + 256 * PEEK(77)
To change where variables are stored, these two commands are used as soon as possible in a program before any variables are created.
To push all variables above $6000 so that the graphics pages are never overwritten accidentally, use LOMEM: 24576
To confine all variables to the graphics page 2 memory region, and protect $0800-$3FFF and $6000-$95FF, use LOMEM:16384 : HIMEM:24575
An advanced memory management trick is to change where BASIC stores programs. This location is configured when BASIC first loads and can be changed when running programs, and is stored at $67-$68 or 103,104 decimal.
For example if you have a very large BASIC program that overlaps hi-res page 1, but you want to use text page 2, hi-res page 1, and hi-res page 2, you can tell DOS and BASIC to load and run programs starting at $6001.
The memory value directly before the start of a BASIC program must be zero, so $6000 is set to 0 before reloading.
10 REM If BASIC program load address is $0801,
20 REM then change to $6001 and reload this program.
30 IF PEEK(104) = 8 THEN POKE 104,96 : POKE 24576,0 :
PRINT "RELOADING" : PRINT CHR$(4)"RUN THIS-PROGRAM"
SAVE THIS-PROGRAM
This also automatically confines variables to above your program between $6000 and the start of DOS.
If you need even more free memory than what DOS 3.3 provides, and you have a 64k or better Apple II, you can use the customized DOS 3.3 called DAVID-DOS, which includes a command called HIDOS.
http://mirrors.apple2.org.za/ftp.apple.asimov.net/images/masters/3rd_party_dos/
This command relocates most of DAVID-DOS into the bank-switched high memory area above $CFFF. Only a small 512 byte stub remains in the 48k memory space, at $BE00-$BFFF, so that it can access the rest of its program code that is sharing memory addresses with the BASIC and Monitor ROM.
$BE00-BFFF - DAVID-DOS bank-switcher 0.5 kB
$6000-BDFF - Free memory 23.5 kB
Finally, if you have a very short assembly language program and you want to avoid all this complexity, it is very common to put short assembly programs in the area of $0300-$03CF as this area is normally not used for anything else and will not be overwritten by BASIC.
EDIT June 1, 2020:
Part of the reasons for these complexities appears to be the high cost of memory when the Apple II was still very new.
According to Wikipedia, the Apple II was first sold in 1977 with only 4 kB of memory installed for US$1298 or with 48 kB of memory for US$2638. This works out to $30.45 per kilobyte in 1977, or $128.83 per kilobyte in 2020, and $11,160 for the 48 kB Apple II in 2020 dollars.
Reference: https://en.wikipedia.org/wiki/Apple_II_series#Apple_II
The first 2 kilobytes enable pages $00 to $07, for the zero page, stack, input buffer, vectors, and text / lo-res page 1.
The second 2 kilobytes enable pages $08 to $0F, providing free memory for BASIC or machine language programs, and loading and saving either of these using cassette tape.
$E000-FFFF - Monitor ROM 8 kB
$D000-DFFF - BASIC ROM 4 kB
$C800-CFFF - Shared slot ROM 2 kB
$C100-C7FF - Permanent Slot ROM 256 per slot
$C000-C0FF - Softswitches 256 bytes
$1000-BFFF - Not usable 44 kB
$0C00-0FFF - Free memory 1 kB
$0800-0BFF - Free memory / Text page 2 1 kB
$0400-07FF - Text page 1 1 kB
$03D0-03FF - Interrupt vectors 48 bytes
$0300-03CF - Free memory 208 bytes
$0200-02FF - Input prompt character buffer 256 bytes
$0100-01FF - CPU stack 256 bytes
$0000-00FF - Zero page 256 bytes
However memory was not required to be installed in contiguous regions across the entire memory address space. Unlike modern computers, there was no memory management circuitry, and the memory socket pins on the motherboard directly correspond to the address map.
It was possible to purchase 8 kB of memory (for about US$1000 in 2020 dollars) and socket it into only memory pages $2000-3FFF to enable high resolution graphics page 1, while leaving the 4 kB at pages $1000-1FFF unusable.
$E000-FFFF - Monitor ROM 8 kB
$D000-DFFF - BASIC ROM 4 kB
$C800-CFFF - Shared slot ROM 2 kB
$C100-C7FF - Permanent Slot ROM 256 per slot
$C000-C0FF - Softswitches 256 bytes
$4000-BFFF - Not usable 32 kB
$2000-3FFF - Hi-res page 1 8 kB
$1000-1FFF - Not usable 4 kB
$0C00-0FFF - Free memory 1 kB
$0800-0BFF - Free memory / Text page 2 1 kB
$0400-07FF - Text page 1 1 kB
$03D0-03FF - Interrupt vectors 48 bytes
$0300-03CF - Free memory 208 bytes
$0200-02FF - Input prompt character buffer 256 bytes
$0100-01FF - CPU stack 256 bytes
$0000-00FF - Zero page 256 bytes