1

I'm wondering if anyone can help me with an annoying issue I face using VASM assembler to compile MC68000 binaries for Amiga. The problem lies in buggy (I think) implementation of labels' addresses manipulations.
Here are the details:

copper_scr:
    dc.w $e0, (screen>>16) & $ffff
    dc.w $e2, screen & $ffff

...

screen:
    dcb.w screen_size  ; screen_size value does not matter here

What I'm trying to do in the code above is to split screen address into most significant word and less significant word in order to feed chip registers with screen data address (or vector if you wish).

However, compilation of code in this shape gives me the "illegal relocation" error 39.

I tried many ways to get rid of this, as I supposed that since screen address is long (i.e. not word) the result of "screen>>16" might remain long and therefore I cannot put such a value into word-wide place.

What's interesting, the following code compiles with no errors, but both values in resulting binary are compiled to a value of 0:

...
dc.w $e0,0 + screen>>16 & $ffff
dc.w $e2,0 + screen&$ffff
...

As a temporal dirty workaround I calculate those values at runtime somewhere at the beginning of code:

move.l #screen,a0
move.l a0,d7
lsr.l #4,d7
lsr.l #4,d7
lsr.l #4,d7
lsr.l #4,d7
andi.l #$ffff,d7
move.w d7,copper_scr+2
move.l a0,d7
andi.l #$ffff,d7
move.w d7,copper_scr+6

but that is obviously ridiculous and totally wrong.

Any help appreciated.

H_nk
  • 13
  • 3
  • How do you build? What arguments do you pass to the assembler? How do you transfer the program to the Amiga? – Some programmer dude Jan 25 '18 at 09:32
  • Here's the command line I use to compile source.s into result.bin: vasmm68k_mot_win32.exe -Fhunkexe -o "result.bin" -nosym "source.s" The result.bin file is located in the folder I set up in FS-UAE emulator as a hard drive, so I can directly run it under emu - but that's not a point. My problem is that I can not even compile the code using the syntax I described in question. :/ – H_nk Jan 25 '18 at 09:49

2 Answers2

3

Nice workaround could be:

move.l  #screen,d0
move.w  d0,scrptr_low+2
swap    d0
move.w  d0,scrptr_high+2
...
scrptr_high: dc.w $e0,0
scrptr_low:  dc.w $e2,0

or

scrptr: dc.l screen
...
move.l  scrptr,d0
<then the same>

This way the linker and exe-loader-relocator will deal with the usual 32-bit addrresses which they know how to relocate properly.

lvd
  • 793
  • 3
  • 12
1

The problem lies in the way the assembler (and linker) works:

Some assemblers already know at which address some code will later be placed while other assemblers write object files and the linker will decide where the data will be placed.

In the object file an instruction like dc.w 1234 + screen>>16 & $ffff will be stored as dc.w 1234 and an additional information is stored that the high 16 bits of screen must be added to 1234 as soon as the address of screen is known.

Unfortunately there are two problems:

  • Not all architectures support all types of information. Object files for Sparc CPUs for example support an information "add the low 10 bits of an address to a value" (because such CPUs have instructions using the low 10 bits of an address) while object files for m68k do not support the "low 10 bits of an address" information type.

    Unfortunately the "high 16 bits of an address" information type is also not supported by m68k object files. (At least not if you use the GNU tools - I'm not sure about VASM.)

  • Assemblers are stupid. They will not detect that screen>>16 & $ffff is equal to "the high 16 bits of an address". So even if your file format (PowerPC object files, for example) supports that type of information the assembler will have a problem.

Possible work-around:

If you have a label in the same section and you definitely know the address of that label you can do the following.

Let's assume you know that the label xyz will be loaded into address $1234 in the memory later.

Now you can do the following:

xyz:
    ...
    dc.w $e0, 0 + (screen - xyz + $1234) >> 16 & $ffff
    ...
screen:

However if you don't know the "final" address of any label you'll have a problem...

Community
  • 1
  • 1
Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • Thank you Martin for your detailed explanation! I've had a feeling that it may have something in common with the "relocationable" nature of MC68000. I'm marking your input as answer since it clearly explains everything. :) Going further however, it turns out that the OS-friendly cross development is not quite possible. What I really wanted was to avoid assigning labels to a fixed addresses. It seems like the only solution for this is obtaining address' high and low words at runtime. Cheers! – H_nk Jan 25 '18 at 10:44
  • It's even a bit more complicated: The absolute value of `screen` depends on the *final load address* of your program and cannot be finally determined, not even by the linker. The linker will just leave some information for the relocating loader that this address has a specific offset from the start of the program. And the relocating loader's capabilities are limited to "patching" these marked addresses with final load addresses (that is, it is limited to simple additions of the base address and that offset) – tofro Feb 04 '18 at 10:16