(*
This is a simple demonstration file for the Zeus assembler.
If you want more sustantial files they're available at www.desdes.com


Segments


Segments are a way to organise where in memory things are put.

For example, when writing a routine you may well want to have both code
and data. Ideally these two things should be placed near to each other in
the source so you can see them together, but in practice they may well
need to be placed far apart in memory. Code might, for example, need to
be placed in one area of memory (FLASH) while data would be placed in 
another (RAM)... Traditionally variables would be placed at the start or
end of memory and the code in the middle, meaning that they were separated 
by many, many lines of source, or alternately the variables would be
interspersed in with the code and so interspersed in real memory. This
makes for both ugly and potentially dangerous code...

Segments let you manipulate the assembly position so that adjacent
statements can refer to different sections of memory. An example might
make this clearer:

	; Now, let's tell Zeus which segments exist and where they belong

	segment code = $6000,$2000	; Starts at $6000, no more than $2000 bytes long
	segment data = $8000,$1000	; Starts at $8000, no more than $1000 bytes long		

	segment code	; Select the code segment

Print		proc			; Print scope starts

		push ix,hl,de,bc,af     ; Save them

                cp cWhite+1             ;
                jr c,PrintColour        ;

		; Etc, etc

                ld a,(pCurX)            ;
                add a,(hl)              ;
                ld (pCurX),a            ;

PrintExit       pop af,bc,de,hl,ix      ;
		ret			;

	segment data	; Select the data segment

; Print variables

pCurX		db 0			; A logical X position
ppCurY		db 0			; A logical Y position
pCurY		dw 0			; The actual address
CurCol		db 0			; The cursor colour
		
	segment code	; Back to the code segment

PrintStr	proc

		; Blah blah...

Now, what Zeus will do is put the PrintStr code immediately after the Print code,
starting at $6000, and the variables will be put starting at $8000.

There's nothing sacred about the names "code" and "data", by the way. You
could call them "george" and "mildred" for all zeus cares.

(From v1.7 onward Zeus will no longer let you use the same name for a segment
and a normal label)

If you don't mention segments at all zeus will behave like a normal z80
assembler and just dump bytes into memory where you tell it too.

If you do mention segments then it is a requirement that you must tell
zeus where the segments start and end before you use them. I have wondered
about allowing zeus to decide on the segment sizes and order in memory
automatically, but there seem to be quite a few little niggles with this,
so for the sort of applications we're talking about for this zeus I've
decided to leave this up to the programmer...

Zeus will, of course, issue error messages if you try to plant code outside
of the range of the current segment.

ORG statements inside a segment are perfectly valid. So are DISP statements
but (of course) these only affect data in that segment.

Segments can overlap. It is undefined what bytes will be placed in memory
when this happens; it will normally be the ones placed by the statements
nearer the end of the combined sources, but this behaviour is subject to
change.


Segment use with macros


Consider a macro that is being used in one segment, when the macro body is 
written in another. Which segment do you think the code generated by the
macro will use? The first. Macros always 'execute' in the context of the
caller. However, should a macro include a segment statement, then that
segment statement will determine the segment used for the rest of the
bytes generated by the macro. When the macro finished zeus will restore
the segment back to the segment being used before the macro call.

When macros are called recursively or from inside other macros the segment
can be changed during each nesting and will be restored on each return.

*)

; Example code to demonstrate segments.
; This code is garbage, it doesn't mean anything

	segment code = $6000,$100	; Starts at $6000, no more than $100 bytes long
	segment data = $6200,$100	; Starts at $6200, no more than $100 bytes long		

	segment code	; Select the code segment

Print		proc			; Print scope starts

		ld hl,Start		; A forward reference to a local label

Start		push ix,hl,de,bc,af     ; Save them

 		; Etc, etc

                ld a,(pCurX)            ;
                add a,(hl)              ;
                ld (pCurX),a            ;

PrintExit       pop af,bc,de,hl,ix      ;
		retp			;

	segment data	; Select the data segment

; Print variables

pCurX		db 1			; A logical X position
ppCurY		db 1			; A logical Y position
pCurY		dw 1			; The actual address
CurCol		db 1			; The cursor colour
		
	segment code	; Back to the code segment

		db 42

		halt
		halt
		halt
		halt


		; Blah blah...


; Tell zeus not to export the symbol table, but to show us any 
; segments

		export_sym "",%1 0 1 00 00	; Blank filename means no export

(*
Now, have a look at the Zeus symbols. The settings in the line above will have
caused (should have caused) the segments to have been added to the symbol table.
The segments are displayed as follows:

code    	 EQU $6000; Length = $0100, Final PC = $601C, Est. size = $001C
data 	         EQU $6200; Length = $0100, Final PC = $6205, Est. size = $0005

Note that the BASE of the segment is the symbol and the LENGTH and Final PC values
are shown as comments. The PC value does not necessarily indicate the maximum size of
the segment, because the PC could have been manipulated using an ORG statement,
but if you have not done anything nasty (backwards ORGs) then you could use
the "Est. size" information to adjust the segment length and base values to arrange
them efficiently in memory.

Remember that Zeus will grump at you if you make the segments too small
so a mistake here shouldn't be silently dangerous...
*)