简体   繁体   English

VASM交叉汇编器问题(M68K)

[英]VASM cross-assembler issue (m68k)

I'm wondering if anyone can help me with an annoying issue I face using VASM assembler to compile MC68000 binaries for Amiga. 我想知道是否有人可以使用VASM汇编器为Amiga编译MC68000二进制文件而遇到的烦人问题。 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. 但是,以这种形状编译代码会给我“非法重定位”错误39。

I tried many ways to get rid of this, as I supposed that since screen address is long (ie not word) the result of "screen>>16" might remain long and therefore I cannot put such a value into word-wide place. 我尝试了多种方法来摆脱这种情况,因为我认为由于屏幕地址很长(即不是单词),因此“ screen >> 16”的结果可能会很长,因此无法将这样的值放在整个单词范围内。

What's interesting, the following code compiles with no errors, but both values in resulting binary are compiled to a value of 0: 有趣的是,下面的代码编译没有错误,但是结果二进制文件中的两个值都被编译为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. 任何帮助表示赞赏。

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. 这样,链接器和exe-loader-relocator将处理它们知道如何正确定位的常规32位地址。

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. 在目标文件中,诸如dc.w 1234 + screen>>16 & $ffff类的指令将被存储为dc.w 1234 ,并且还存储了附加信息,即地址一经添加, screen的高16位就必须添加到1234中。 screen是已知的。

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. 例如,Sparc CPU的目标文件支持信息“ 将地址的低10位添加到值中 ”(因为此类CPU的指令使用地址的低10位),而m68k的目标文件不支持“ 低10位”信息地址信息类型的位。

    Unfortunately the " high 16 bits of an address " information type is also not supported by m68k object files. 不幸的是,m68k目标文件也不支持“ 地址的高16位 ”信息类型。 (At least not if you use the GNU tools - I'm not sure about VASM.) (至少如果您使用GNU工具,则不会-我不确定VASM。)

  • Assemblers are stupid. 汇编程序很愚蠢。 They will not detect that screen>>16 & $ffff is equal to " the high 16 bits of an address ". 他们将不会检测到screen>>16 & $ffff等于“ 地址的高16位 ”。 So even if your file format (PowerPC object files, for example) supports that type of information the assembler will have a problem. 因此,即使您的文件格式(例如PowerPC目标文件)支持该类型的信息,汇编器也会出现问题。

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. 假设您知道标签xyz稍后将被加载到内存中的地址$1234中。

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... 但是,如果您不知道任何标签的“最终”地址,就会遇到问题...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM