Segment
A segment is a named region of memory that holds code or data, and can optionally be written to a file.
Every program has a Main segment. You can add more, anywhere in memory: a BSS-style block of uninitialised RAM, a zero-page area for hot variables, or several segments that share a RAM bank address.
A segment with no filename is fine as long as it holds nothing but reserved space. Give it code or initialised data with no filename and the build fails. Without a maxsize a segment grows freely; with one, overflowing it is an error.
Main
Main is the segment every program starts in. It begins at $0801, where the X16 loads a BASIC program, and a program run from BASIC has to fit between there and the I/O area at $9f00.
Its output file is the source file’s name with the extension changed to .prg, written with a two-byte load address at the front. .endsegment returns to Main from any other segment.
Defining a segment
.segment opens a segment; naming one that already exists switches back to it.
| Name | Type | Optional | Description |
|---|---|---|---|
name |
string | no | The segment’s name. Naming an existing segment switches to it, and any other parameters given are applied. |
address |
number | yes | Where it sits in memory. Settable only before the segment has any code or data. If omitted, it follows on from the current segment. |
maxsize |
number | yes | Maximum size. Overflowing it is an error. |
filename |
string | yes | File to write for this segment. |
scope |
string | yes | Also switches to this scope, a shortcut for a .segment followed by a .scope. Without it, .segment switches to the Main scope. |
Define the memory map in one place
Use !segment in your main .bmasm file to define every segment up front: where it sits, how big it can be, and the file it’s written to. The whole memory map and all the output files are then in one place, rather than spread across the files that use them.
The ! prefix runs the line before anything else in the build, including every library’s code, so each segment is set up before anything writes to it:
; main.bmasm
import Music="music.bmasm";
; the memory map: each segment's address, maximum size and output file
!segment ZP $22 $5d _ ; zero page, no file
!segment MUSIC $a000 $2000 MUSIC.BIN ; RAM bank code, written to MUSIC.BIN
!segment SNDFX $a000 $2000 SNDFX.BIN ; another bank, written to SNDFX.BIN
.machine CommanderX16R42
...
The rest of the program, libraries included, then opens a segment by name alone:
; music.bmasm
file library
section code
.segment MUSIC ; at $a000, as main.bmasm set it
.scope music
.proc tick
...
rts
.endproc
.endscope
.endsegment
!only works in the main file; in a library it does nothing.!segmentbecomes.segmentdefine, so it only defines the segment and doesn’t switch to it. The current segment stays as it was.!segmentdoesn’t take ascope, as it doesn’t switch. Give the scope on the.segmentthat opens the segment, as the library above does with.scope.- Without the definition, the library’s
.segment MUSICcreates the segment straight after the current one, with no filename, and the build fails withSegment 'MUSIC' has data, but no filename.
Viewing segments
Set the displaySegments compile option to list every segment and its extent in the build output:
Segment Start Size End
Main $0801 $0145 $0946
Examples
A BSS area
Reserved RAM from $400, $400 bytes long, with no file. On the X16 the $400 to $800 region is free for this, as is $200 to $3ff if you are not using the KERNAL.
.segment BSS $400 $400
Zero page
The zero page is where you keep your most-used variables. Here the segment runs from $22 for up to $5d bytes, takes the scope app_general, and _ skips the filename:
.segment ZP $22, $5d, _, app_general
Several segments, one RAM bank
Addresses are always from the CPU’s point of view, so segments destined for different RAM banks all start at $a000. It is up to you to page the right bank in before touching each one.
Define them together so the layout lives in one place:
.segment MUSIC $a000 $2000 MUSIC.BIN
.segment SNDFX $a000 $2000 SNDFX.BIN
.endsegment ; back to Main
To keep them with the rest of your memory map, define them with ! in your main file instead (see Define the memory map in one place):
!segment MUSIC $a000 $2000 MUSIC.BIN
!segment SNDFX $a000 $2000 SNDFX.BIN