VASM 交叉汇编程序问题 (m68k)
VASM cross-assembler issue (m68k)
我想知道是否有人可以帮助我解决我在使用 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
我在上面的代码中试图做的是将屏幕地址拆分为最高有效字和次要字,以便将屏幕数据地址(或矢量,如果您愿意)提供给芯片寄存器。
但是,以这种形式编译代码会出现 "illegal relocation" 错误 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
但这显然是荒谬和完全错误的。
感谢任何帮助。
问题在于汇编器(和链接器)的工作方式:
一些汇编程序已经知道稍后将放置某些代码的地址,而其他汇编程序则编写目标文件,链接器将决定数据的放置位置。
在目标文件中,像 dc.w 1234 + screen>>16 & $ffff
这样的指令将被存储为 dc.w 1234
并且存储了一个额外的信息,即 screen
的高 16 位必须添加到 [=14] =] 一旦知道 screen
的地址。
不幸的是有两个问题:
并非所有体系结构都支持所有类型的信息。例如,Sparc CPU 的目标文件支持信息“将地址的低 10 位添加到值”(因为此类 CPU 具有使用地址的低 10 位的指令)而对象m68k 的文件不支持“地址的低 10 位”信息类型。
不幸的是,m68k 目标文件也不支持“地址的高 16 位”信息类型。 (至少如果您使用 GNU 工具则不会——我不确定 VASM。)
汇编程序是愚蠢的。他们不会检测到 screen>>16 & $ffff
等于“地址的高 16 位 ”。因此,即使您的文件格式(例如 PowerPC 对象文件)支持该类型的信息,汇编程序也会出现问题。
可能的解决方法:
如果您在 相同的 部分中有一个标签,并且您肯定知道该标签的地址,则可以执行以下操作。
假设您知道标签 xyz
稍后将加载到内存中的地址 34
。
现在您可以执行以下操作:
xyz:
...
dc.w $e0, 0 + (screen - xyz + 34) >> 16 & $ffff
...
screen:
但是,如果您不知道任何标签的“最终”地址,您就会遇到问题...
不错的解决方法可能是:
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 位地址。
我想知道是否有人可以帮助我解决我在使用 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
我在上面的代码中试图做的是将屏幕地址拆分为最高有效字和次要字,以便将屏幕数据地址(或矢量,如果您愿意)提供给芯片寄存器。
但是,以这种形式编译代码会出现 "illegal relocation" 错误 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
但这显然是荒谬和完全错误的。
感谢任何帮助。
问题在于汇编器(和链接器)的工作方式:
一些汇编程序已经知道稍后将放置某些代码的地址,而其他汇编程序则编写目标文件,链接器将决定数据的放置位置。
在目标文件中,像 dc.w 1234 + screen>>16 & $ffff
这样的指令将被存储为 dc.w 1234
并且存储了一个额外的信息,即 screen
的高 16 位必须添加到 [=14] =] 一旦知道 screen
的地址。
不幸的是有两个问题:
并非所有体系结构都支持所有类型的信息。例如,Sparc CPU 的目标文件支持信息“将地址的低 10 位添加到值”(因为此类 CPU 具有使用地址的低 10 位的指令)而对象m68k 的文件不支持“地址的低 10 位”信息类型。
不幸的是,m68k 目标文件也不支持“地址的高 16 位”信息类型。 (至少如果您使用 GNU 工具则不会——我不确定 VASM。)
汇编程序是愚蠢的。他们不会检测到
screen>>16 & $ffff
等于“地址的高 16 位 ”。因此,即使您的文件格式(例如 PowerPC 对象文件)支持该类型的信息,汇编程序也会出现问题。
可能的解决方法:
如果您在 相同的 部分中有一个标签,并且您肯定知道该标签的地址,则可以执行以下操作。
假设您知道标签 xyz
稍后将加载到内存中的地址 34
。
现在您可以执行以下操作:
xyz:
...
dc.w $e0, 0 + (screen - xyz + 34) >> 16 & $ffff
...
screen:
但是,如果您不知道任何标签的“最终”地址,您就会遇到问题...
不错的解决方法可能是:
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 位地址。