我想知道是否有人可以帮助我解决我使用VASM汇编程序为Amiga编译MC68000二进制文件时遇到的烦人问题。问题在于错误(我认为)标签的地址操作的实现 以下是详细信息:
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
我在上面的代码中尝试做的是将屏幕地址分成最重要的单词和不太重要的单词,以便为芯片寄存器提供屏幕数据地址(或者如果你愿意的话,可以传送矢量)。
但是,编译此形状的代码会给我带来“非法重定位”错误39。
我尝试了很多方法摆脱这种情况,因为我认为由于屏幕地址很长(即不是字),“screen>> 16”的结果可能会保持很长时间,因此我无法将这样的值放入字中全场。
有趣的是,以下代码编译时没有错误,但结果二进制中的两个值都编译为0:
...
dc.w $e0,0 + screen>>16 & $ffff
dc.w $e2,0 + screen&$ffff
...
作为一个时间脏的解决方法,我在代码开头的某处运行时计算这些值:
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
但这显然是荒谬而完全错误的。
任何帮助表示感谢。
答案 0 :(得分:3)
好的解决方法可能是:
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
或
scrptr: dc.l screen
...
move.l scrptr,d0
<then the same>
这样链接器和exe-loader-relocator将处理通常的32位地址,他们知道如何正确地重新定位。
答案 1 :(得分:1)
问题在于汇编程序(和链接程序)的工作方式:
一些汇编程序已经知道某些代码将在哪个地址放置,而其他汇编程序编写目标文件,链接器将决定数据的放置位置。
在目标文件中,dc.w 1234 + screen>>16 & $ffff
之类的指令将存储为dc.w 1234
,并存储一条附加信息,其中screen
的高16位必须添加到1234
只要知道screen
的地址。
不幸的是有两个问题:
并非所有架构都支持所有类型的信息。例如,Sparc CPU的目标文件支持信息“将地址的低10位添加到值”(因为此类CPU具有使用地址的低10位的指令),而m68k的目标文件不支持“低10位地址”信息类型。
不幸的是,m68k对象文件也不支持“高16位地址”信息类型。 (至少如果你使用GNU工具则没有 - 我不确定VASM。)
汇编是愚蠢的。他们不会检测到screen>>16 & $ffff
等于“地址的高16位”。因此,即使您的文件格式(例如PowerPC对象文件)支持该类型的信息,汇编器也会出现问题。
可能的解决方法:
如果您在相同部分中有标签,并且您肯定知道该标签的地址,则可以执行以下操作。
我们假设您知道标签xyz
稍后会被加载到内存中的地址$1234
。
现在您可以执行以下操作:
xyz:
...
dc.w $e0, 0 + (screen - xyz + $1234) >> 16 & $ffff
...
screen:
但是,如果您不知道任何标签的“最终”地址,那么您将遇到问题......