我不知道是否有人能帮助我与我的脸用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。
我尝试过很多办法摆脱这一点,因为我认为,既然画面地址是长(即不是字)的结果“屏幕>> 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
和附加信息存储在该高16位screen
必须被添加到1234
只要地址的screen
是已知的。
不幸的是两个问题:
并非所有的体系结构都支持所有类型的信息。 目标文件的SPARC CPU例如支持信息“ 添加一个地址的值的低10位 ”(因为这样的CPU具有使用地址的低10位指令),而m68k的对象文件不支持“ 低10地址 “信息类型的比特 。
不幸的是信息类型“ 地址的高16位 ”也不会被m68k的目标文件的支持。 (至少不是,如果你使用GNU工具 - 我不知道VASM。)
汇编是愚蠢的。 他们不会检测到screen>>16 & $ffff
等于“ 地址的高16位 ”。 所以,即使你的文件格式(PowerPC的目标文件,例如)支持这种类型的信息汇编器有问题。
可能的解决方法:
如果在同一节的标签,你一定知道该标签的地址,你可以做到以下几点。
让我们假设你知道标签xyz
将被加载到地址$1234
后在内存中。
现在,你可以做到以下几点:
xyz:
...
dc.w $e0, 0 + (screen - xyz + $1234) >> 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加载器,重新定位将处理与通常的32位addrresses,他们知道如何正确地搬迁。