Dealing with double inclusion in Zeus

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Dealing with double inclusion in Zeus

Post by djnzx48 »

This is a problem I've been dealing with recently with the Zeus assembler. So I have a file called 'main.asm', which includes two files 'a.asm' and 'b.asm'. Now these two files both include a file 'common.asm'. However, this setup results in errors as everything in 'common.asm' ends up getting declared twice.

I tried getting around the problem by using include guards like this:

Code: Select all

; in common.asm:

if !def COMMON_ASM
COMMON_ASM equ 1

; code goes here

endif
But that didn't work as the assembler goes round for another pass after the symbol is defined, and everything within the include guard just gets ignored. So is there a way to get this to work?
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Dealing with double inclusion in Zeus

Post by Seven.FFF »

It probably depends on what’s inside common.asm, and what you’re trying to achieve.

Does Common.asm just have equ definitions, or code as well?

Are you expecting the equs to get the same values both times?

If it has code inside, are you expecting a separate copy of the code to get assembled for each inclusion?

Is there a particular reason you’re deliberately including the file twice?
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
crem
Drutt
Posts: 1
Joined: Tue Jun 12, 2018 12:51 am

Re: Dealing with double inclusion in Zeus

Post by crem »

Well, few assemblers will deal with this situation correctly, since having multiple includes means having multiple definitions of the same labels... but Zeus is capable of dealing with this in a number of ways.

Let's talk about files "main.asm" which includes "a.inc" and "b.inc" both of which include file "common.inc"...

Zeus will be perfectly happy about this as long as "common.inc" just declares variables or constant labels, because Zeus will let you have multiple declarations of the SAME label as long as you give it the same value... if you don't have the same value then your source is deformed and inconsistent and it's the assembler's job to detect that situation and reject it, as Zeus does.

That covers most common definition files... but you are reporting a problem so I'm guessing that you have something in your "common.inc" that is causing label values to change, for example including some data definitions or code. Let's consider the case where "common.inc" includes a bit of code... say this:

DoNothing ret

Now, the problem is that when you first include it that code is given an address, and then when you include it a second time it is given a different address, which means that the label DoNothing has inconsistent values and Zeus will report this (correctly) as an error.

How to avoid the problem? Aside from not including the same code multiple times? Well, there are a number of ways.

The simplest approach is to put an ORG statement in common.inc so that Zeus always puts it in the same place no matter how many times you include it... then the labels will never change and your source code will be consistent. There are two things to be considered - first you need to think about where you want to put the common code rather than leaving it up to Zeus... secondly after leaving the "common.inc" source the assembly position will be left at the end of the common code, and that needs dealing with or your various other sources will overwrite each other. This might involve giving them ORGs or writing two lines of code in "common.inc" to save the assembly position at the start and restore it at the end...

A better approach is to use segments, and give the common.inc code its own segment. Here is an example "common.inc" skeleton:

;------------

; Common file

; Declare a couple of segments, or more if you like
segment Code=$8000,$7F00 ; Typical Spectrum fast memory
segment Common=$FF00,$100 ; Reserve a bit at the top for the Common code

; Use the Common segment for the common code
segment Common

; Our dummy routine
DoNothing ret

; Presume everything else is in the Code segment
segment Code

;------------

Something like that...
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Dealing with double inclusion in Zeus

Post by djnzx48 »

OK, that makes sense, thanks. It looks like using segments would be a good option here.
Post Reply