Re: A89: xdef, ea


[Prev][Next][Index][Thread]

Re: A89: xdef, ea




 > Could someone please explain what xdef is to me?  And also explain what
 > an effective address is?  Thanks.

The effective address is the location of an operand of an operation. 
The effective address in its general form can be a register, a
constant, a memory location, anything. If you take a look a the the
Motorola books you will find that they say for example:

   add <ea>,Dn
   
which means 'add the content of <ea> to the data register Dn' and you
get a table of different <ea> -s: an other data register, an address
register, a constant or any form of memory reference which you either
specify directly:

   add my_variable,d3
   
or the CPU will calculate it on the fly:

   add 16(a0,d1),d3
   
in which case the effective address (where the operand is) is 'the
memory location at the address of the content of a0 plus the content
of d1 plus 16'.

In case of the lea (Load Effective Address) and pea (Push Effective
Address) instructions the meaning of the <ea> is limited to real
memory addresses - the instructions load the effective address (and
not the value found at that address) to a register, or push it to the
stack, respectively. By the way, it is an old trick to use lea if you
want to push a 16-bit constant as a 32-bit number to the stack:

Instead of

   moveq.l #0,d0             ; 1 word,  1 cycle
   move.w  #a_constant,d0    ; 2 words, 2 cycles
   move.l  d0,-(sp)          ; 1 word,  3 cycles
   
                         SUM : 4 words, 6 cycles
   
you write

   pea     a_constant        ; 2 words, 4 cycles
   
The same trick can be used when you want to load a 16 bit value to an
address register extended to 32 bit (using lea, of course).
(Note that this will sign-extend your constant so your actual range is
-32767 - 32767 and not 0 - 65535, which would be the case with the
longer method.) You will also find that most C compilers use this
trick, if you take a look at the generated code.

The 'xdef' is a directive, which is assembler dependent and means that 
the object is accessible from other files.

If you have a complex enough code you don't want to keep the lot in
one single file. Say you write some subroutines that handle sprites. 
Then you write your game in an other file (so that you don't have to
skip over the sprite routines all the time in your editor and for a
dozen of other reasons) but you want to call MoveSprite from it. 
The assembler will give you an error saying MoveSprite: undefined
symbol. So you put

   xref  MoveSprite
   
in your game source, telling the assembler that it shouldn't look for
MoveSprite because it is defined in an other file. However, when you
link the game object and the sprite object, the linker will bark along 
the lines of unresolved symbol MoveSprite. It is because by default
the visibility of symbols defined in a file is limited to that file.
Otherwise if someone used the symbol 'x' in a file then that symbol
could not be used in any other file that you link with the first one
together. This wouldn't be a problem if you were the only person
writing everything, but as soon as you want to use two pieces, written 
by two independent individuals, you can't avoid name clashing.
Therefore, the symbols are always local *unless* you explicitly tell
the assembler to make a symbol public or global. This is what the 

   xdef  MoveSprite
   
directive does, instructs the assembler to generate a message
(embedded in the object file, of course) to the linker that the 
MoveSprite symbol should be visible to every other bit of code, 
if they say that they want to refer to it (using the xref MoveSprite 
directive). 

The actual name and mechanism depend on the assembler (even the
assembler version), for example there are assemblers which use the
same directive for both 'xdef' and 'xref': if the symbol is defined 
in the file, the directive will act as 'xdef', it is isn't, it will 
be equivalent to an 'xref'.
Still others will implicitly declare undefined symbols external, that
is, all undefined symbols will be 'xref <symbol>' -ed by the assembler 
automagically - you will *never* get an undefined symbol error from 
the assembler, only from the linker. (This is how the GNU assembler 
behaves, by the way). 
Still others, e.g. m80, the Z80/8080 assembler from Microsoft (in the 
late seventies - early eighties, for CP/M) used the directives but as
a shorthand, you could made a symbol public if you added two colons 
after it and treated it as external if you appended a hashmark after 
its name:

local_symbol:             ; this simbol is visible only from this file
my_routine::              ; makes it visible from other places as well
    ld   bc,a_symbol#     ; indicates that a_symbol is declared elsewhere
    ld   hl,other_symbol  ; other_symbol must be defined in this file
	
So there are countless ways to actually express what symbol is to be
published or exported or defined as global and, pairing it, tell that 
a symbol is referenced or imported or declared as global.

The concept remains the same: unless you tell so, most symbols are
confined within the single source they are defined. The ones which
needed to provide communication between the files are made public
and referenced from other files but you have to explicitly tell the
assembler that you want them to behave this way.

Regards,

Zoltan


Follow-Ups: References: