使用 Motorola 68000 汇编语法中的程序计数器间接索引语法

7
我正在为Sega Mega Drive ROMs制作自己的反汇编器,最初的工作基于MOTOROLA M68000 FAMILY Programmer’s Reference Manual。在反汇编了相当一部分ROM之后,我尝试使用VASM重新组装这个反汇编输出,因为它可以接受Motorola汇编语法,并使用其mot 语法模块
现在,对于绝大多数重新组装,这个方法很有效,但是有一个问题是操作的有效地址由“程序计数器间接带索引(8位位移)模式”定义。考虑到我现在才开始学习Motorola 68000汇编语言,我想确认我的理解并问一下:这些操作的正确语法是什么?
例如,如果我有两个单词:
4ebb 0004

我将其解释为目标地址是以下内容的JSR:
  • pc的内容
  • 0x04
  • d0的内容
(考虑到我仅限于68000,因此省略了扩展字中“size”和“scale”的任何考虑)根据参考手册中对该寻址模式的描述,我已将其转换为:
jsr ($04,pc,d0)

使用VASM进行汇编

然而,当我将此反馈到VASM时,它会发出以下错误:

error 2030 in line X of "XXXX.asm": displacement out of range
>  jsr ($04,pc,d0)

这个错误看起来很奇怪,因为由于使用 d0 寄存器,位移量直到运行时才能确定。通过尝试,似乎它使用操作数的第一部分($04)作为绝对目标地址,并基于此计算不同的位移量。

使用 GNU as 汇编

如果我切换到 GNU as,提供与原始 ROM 相同输出的语法为:

jsr %pc@(0x04,%d0:w)

这似乎表明操作数的第一部分是位移量。然而,当我使用objdump反汇编时,列出的指令是:

jsr %pc@(0x6,%d0:w)

这似乎表明,在as使用的MIT语法中,操作数的第一部分再次是绝对地址。

终极问题

这两种语法之间的混淆,甚至包括as汇编和后续反汇编之间的混淆,让我想知道正确的语法应该是什么,或者是否使用这种寻址模式的指令往往由汇编器作为宏或其他更高级别的结构的一部分生成。

调查结果摘要

思考@tofro提出的观点,我找到了正确的方向,以下是我的结论:

使用标签

我测试过的两个汇编器(VASM和GNU as)都会正确处理在我认为的操作数“位移”部分提供的标签,并根据当前PC和目标标签计算位移。鉴于从程序员的角度来看这种方式的方便性以及@tofro的观察,我认为这就是这种寻址方式的预期用法。

因此,使用vasm汇编以下内容:

  org   $80

  jsr   (label,pc,d0)
  nop

label:
  nop

生成一个类似如下的清单文件:
Sections:
00: "seg80" (80-88)


Source: "vasm-label.asm"
                                     1:   org   $80
                                     2: 
00:00000080 4EBB0004                 3:   jsr   (label,pc,d0)
00:00000084 4E71                     4:   nop
                                     5: 
                                     6: label:
00:00000086 4E71                     7:   nop
                                     8: 


Symbols by name:
label                            A:00000086

Symbols by value:
00000086 label

使用 as 组装以下内容:

  .org  0x80

  jsr   %pc@(label,%d0:w)
  nop

label:
  nop

生成一个类似于以下的清单文件:
68K GAS  as-label.asm           page 1


   1 0000 0000 0000       .org  0x80
   1      0000 0000 
   1      0000 0000 
   1      0000 0000 
   1      0000 0000 
   2                
   3 0080 4EBB 0004       jsr   %pc@(label,%d0:w)
   4 0084 4E71            nop
   5                
   6                label:
   7 0086 4E71            nop
68K GAS  as-label.asm           page 2


DEFINED SYMBOLS
        as-label.asm:6      .text:0000000000000086 label

NO UNDEFINED SYMBOLS

我们可以看到,两个汇编器都针对该指令输出了相同的两个单词(与我的原始示例相同):
4ebb 0004

往后看,一旦我的反汇编中所有标签都被正确识别,这将是最用户友好的格式。

使用直接“位移”

这就是两者的区别所在,关键在于它们如何处理操作数中提供的“位移”部分,是作为位移还是目标地址。

回到vasm,进行汇编:

  org   $80

  jsr   ($04,pc,d0)
  nop

label:
  nop

生成:

Sections:
00: "seg80" (80-88)


Source: "vasm-disp.asm"
                                     1:   org   $80
                                     2: 
00:00000080 4EBB0082                 3:   jsr   ($04,pc,d0)
00:00000084 4E71                     4:   nop
                                     5: 
                                     6: label:
00:00000086 4E71                     7:   nop
                                     8: 


Symbols by name:
label                            A:00000086

Symbols by value:
00000086 label

展示了提供的位移($04)被视为操作数的基本目标,并计算并发出一个负偏移量(0x82-0x7e)。
与之相比,使用as进行汇编时:
  .org  0x80

  jsr   %pc@(0x04,%d0:w)
  nop

label:
  nop

产生:

68K GAS  as-disp.asm            page 1


   1 0000 0000 0000       .org  0x80
   1      0000 0000 
   1      0000 0000 
   1      0000 0000 
   1      0000 0000 
   2                
   3 0080 4EBB 0004       jsr   %pc@(0x04,%d0:w)
   4 0084 4E71            nop
   5                
   6                label:
   7 0086 4E71            nop
68K GAS  as-disp.asm            page 2


DEFINED SYMBOLS
         as-disp.asm:6      .text:0000000000000086 label

NO UNDEFINED SYMBOLS

显示提供的值(0x04)被视为位移,并直接编码到输出字节中。
在我的情况下,当使用VASM调整反汇编算法时,能够传递未解析标签的完整地址作为操作数是非常有用的,因此这很可能是我现在要使用的方法。
1个回答

6
我认为,两者都。
  jsr <displacement>(pc,<data register>)

或者

  jsr (<displacement>,pc,<data register>)

正确的语法。但是

没有人会在汇编程序中编写这样的代码(监视器程序可能有所不同)。每个汇编器期望的是一个(可重定位)标签而不是文字数字来计算PC偏移量。然后,它将从当前PC和标签之间的距离计算数值偏移量。您只是混淆了该机制。

如果你使用任何其他地址寄存器而不是PC,你可能会发现你的语法被接受。大多数汇编器都不喜欢文字PC偏移量。您应该预期类似于短相对分支的情况。

 bra.s -4

编辑:

我的汇编器似乎可以理解这样的结构,如果位移被明确标记为可重定位地址并将其与“*”(当前PC)相关联,例如

 jsr *-4(pc,d0.w)

(虽然没有尝试vasm)


感谢@tofro。解决了你在这里提出的问题,帮助我澄清了我尝试的汇编器所期望的内容,并且我能够成功地复制原始操作码字节。我会将此标记为正确答案并将我的发现添加到我的问题中✌️。 - msbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接