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:
; 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?
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