Motorola 68000 带有索引的程序计数器间接汇编语法

msb*_*bit 7 assembly 68000 gnu-assembler disassembly addressing-mode

我已经根据MOTOROLA M68000 FAMILY Programmer\xe2\x80\x99s Reference Manual编写了自己的Sega Mega Drive ROM 反汇编程序。拆卸了相当大的 ROM 块后,我尝试使用VASM重新组装这个拆卸的输出,因为它可以使用其语法模块接受摩托罗拉汇编语法。mot

\n

现在,对于绝大多数重组来说,这种方法效果很好,但是,对于具有由“带索引(8 位位移)模式的程序计数器间接”定义的有效地址的操作,存在一个问题。鉴于我现在才学习 Motorola 68000 组装,我想确认我的理解并问:这些操作的正确语法是什么?

\n

解释

\n

例如,如果我有两个词:

\n
4ebb 0004\n
Run Code Online (Sandbox Code Playgroud)\n

我将其解释为JSR目标目的地是以下各项的总和:

\n
    \n
  • 的内容pc
  • \n
  • 0x04
  • \n
  • 的内容d0
  • \n
\n

(鉴于我将自己限制在 68000,我在扩展字中省略了对sizeand的任何考虑scale)。\n根据参考手册中如何描述此寻址模式,我将其发出为:

\n
jsr ($04,pc,d0)\n
Run Code Online (Sandbox Code Playgroud)\n

使用 VASM 进行组装

\n

但是,当我将其反馈回 VASM 时,它会发出以下错误:

\n
error 2030 in line X of "XXXX.asm": displacement out of range\n>  jsr ($04,pc,d0)\n
Run Code Online (Sandbox Code Playgroud)\n

这似乎是一个非常奇怪的错误,因为由于寄存器的使用,位移直到运行时才能知道d0。尝试一下,它似乎使用操作数的第一部分($04)作为绝对目标目的地,并基于此计算不同的位移。

\n

使用 GNU 进行汇编as

\n

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

\n
jsr %pc@(0x04,%d0:w)\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
jsr %pc@(0x6,%d0:w)\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

终极问题

\n

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

\n

调查结果摘要

\n

思考@tofro 的观点让我朝着正确的方向前进,这就是我得出的结论:

\n

使用标签

\n

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

\n

因此,将以下内容组装为vasm

\n
  org   $80\n\n  jsr   (label,pc,d0)\n  nop\n\nlabel:\n  nop\n
Run Code Online (Sandbox Code Playgroud)\n

生成一个如下所示的列表文件:

\n
Sections:\n00: "seg80" (80-88)\n\n\nSource: "vasm-label.asm"\n                                     1:   org   $80\n                                     2: \n00:00000080 4EBB0004                 3:   jsr   (label,pc,d0)\n00:00000084 4E71                     4:   nop\n                                     5: \n                                     6: label:\n00:00000086 4E71                     7:   nop\n                                     8: \n\n\nSymbols by name:\nlabel                            A:00000086\n\nSymbols by value:\n00000086 label\n
Run Code Online (Sandbox Code Playgroud)\n

并用 组装以下内容as

\n
  .org  0x80\n\n  jsr   %pc@(label,%d0:w)\n  nop\n\nlabel:\n  nop\n
Run Code Online (Sandbox Code Playgroud)\n

生成一个如下所示的列表文件:

\n
68K GAS  as-label.asm           page 1\n\n\n   1 0000 0000 0000       .org  0x80\n   1      0000 0000 \n   1      0000 0000 \n   1      0000 0000 \n   1      0000 0000 \n   2                \n   3 0080 4EBB 0004       jsr   %pc@(label,%d0:w)\n   4 0084 4E71            nop\n   5                \n   6                label:\n   7 0086 4E71            nop\n68K GAS  as-label.asm           page 2\n\n\nDEFINED SYMBOLS\n        as-label.asm:6      .text:0000000000000086 label\n\nNO UNDEFINED SYMBOLS\n
Run Code Online (Sandbox Code Playgroud)\n

我们可以看到两个汇编器都为指令输出相同的两个单词(按照我原来的示例):

\n
4ebb 0004\n
Run Code Online (Sandbox Code Playgroud)\n

展望未来,一旦在我的反汇编中正确识别了所有标签,这将是最用户友好的格式。

\n

使用直接“位移”

\n

这就是两者的不同之处,归结为它们是将提供的操作数的“位移”部分视为位移还是目标地址。

\n

回到vasm,组装:

\n
  org   $80\n\n  jsr   ($04,pc,d0)\n  nop\n\nlabel:\n  nop\n
Run Code Online (Sandbox Code Playgroud)\n

产生:

\n
Sections:\n00: "seg80" (80-88)\n\n\nSource: "vasm-disp.asm"\n                                     1:   org   $80\n                                     2: \n00:00000080 4EBB0082                 3:   jsr   ($04,pc,d0)\n00:00000084 4E71                     4:   nop\n                                     5: \n                                     6: label:\n00:00000086 4E71                     7:   nop\n                                     8: \n\n\nSymbols by name:\nlabel                            A:00000086\n\nSymbols by value:\n00000086 label\n
Run Code Online (Sandbox Code Playgroud)\n

显示提供的位移 ( $04) 被视为操作数的基本目标,并计算并发出负偏移量​​ (0x82或)。-0x7e

\n

将此与as, 进行对比,其中组装:

\n
  .org  0x80\n\n  jsr   %pc@(0x04,%d0:w)\n  nop\n\nlabel:\n  nop\n
Run Code Online (Sandbox Code Playgroud)\n

产生:

\n
68K GAS  as-disp.asm            page 1\n\n\n   1 0000 0000 0000       .org  0x80\n   1      0000 0000 \n   1      0000 0000 \n   1      0000 0000 \n   1      0000 0000 \n   2                \n   3 0080 4EBB 0004       jsr   %pc@(0x04,%d0:w)\n   4 0084 4E71            nop\n   5                \n   6                label:\n   7 0086 4E71            nop\n68K GAS  as-disp.asm            page 2\n\n\nDEFINED SYMBOLS\n         as-disp.asm:6      .text:0000000000000086 label\n\nNO UNDEFINED SYMBOLS\n
Run Code Online (Sandbox Code Playgroud)\n

表明提供的值 ( 0x04) 被视为位移,并直接编码到输出字节中。

\n

在我的情况下,在使用 VASM 时能够传递操作数中未解析标签的完整地址在微调反汇编算法时非常有用,因此这很可能是我现在将使用的。

\n

tof*_*fro 6

在我看来,两者

  jsr <displacement>(pc,<data register>)
Run Code Online (Sandbox Code Playgroud)

或者

  jsr (<displacement>,pc,<data register>)
Run Code Online (Sandbox Code Playgroud)

是正确的语法。但

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

您可能会发现,如果您使用除 PC 之外的任何其他地址寄存器,您的语法可能会被接受。大多数汇编器根本不喜欢字面的 PC 偏移量。您应该期待与较短的相关分支类似的内容,例如

 bra.s -4
Run Code Online (Sandbox Code Playgroud)

编辑:

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

 jsr *-4(pc,d0.w)
Run Code Online (Sandbox Code Playgroud)

(不过没有尝试vasm)