1

我想知道是否有人可以帮助我解决使用 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

但这显然是荒谬和完全错误的。

任何帮助表示赞赏。

4

2 回答 2

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 位地址。

于 2018-01-26T13:11:43.183 回答
1

问题在于汇编器(和链接器)的工作方式:

一些汇编器已经知道稍后将一些代码放置在哪个地址,而其他汇编器编写目标文件,链接器将决定数据的放置位置。

在目标文件中,dc.w 1234 + screen>>16 & $ffff将存储类似的指令,dc.w 1234并存储附加信息,一旦知道地址,就screen必须将其高 16 位添加到。1234screen

不幸的是有两个问题:

  • 并非所有架构都支持所有类型的信息。例如,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:

但是,如果您不知道任何标签的“最终”地址,您就会遇到问题......

于 2018-01-25T10:00:12.230 回答