我一直在为Sega Mega驱动器 ROM组装自己的反汇编程序,最初的工作是基于摩托罗拉M68000系列程序员参考手册。在拆卸了相当一部分ROM之后,我尝试使用VASM重新组装这个拆卸的输出,因为它可以接受摩托罗拉的组装语法,使用它的语法模块。
现在,对于绝大多数的重组,这是很好的工作,但有一个皱纹的操作,有有效的地址定义的“程序计数器间接索引(8位位移)模式”。考虑到我现在才开始学习摩托罗拉68000程序集,我想确认我的理解,并问:这些操作的正确语法是什么?
释义
例如,如果我有两个词:
4ebb 0004我将其解释为一个JSR,目标目的地是以下之和:
pc含量0x04d0含量(考虑到我将自己限制在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相同输出的语法是:
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时,能够在操作数中传递未解析标签的完整地址对于细化反汇编算法非常有用,所以这很可能是我现在将要使用的。
发布于 2022-02-27 11:53:24
在我看来,两者
jsr <displacement>(pc,<data register>)或
jsr (<displacement>,pc,<data register>)是正确的语法。但
没有人会把这样的代码写到汇编程序中。每个汇编程序所期望的(监视程序可能有所不同)是一个(可重定位的)标签,而不是计算PC偏移量时的文字编号。然后计算当前PC与标签之间距离的数值位移。你只是把这个机制弄糊涂了。
您可能会发现,如果您使用任何其他地址寄存器,但PC,您的语法可能会被接受。大多数汇编程序根本不喜欢文字PC偏移。您应该期待类似于短相对分支的东西,如
bra.s -4编辑:
我的汇编程序似乎理解这样的结构,如果位移被明确地标记为一个可重定位的地址,将其与"*“(当前的PC) (如
jsr *-4(pc,d0.w)(但没有尝试vasm )
https://stackoverflow.com/questions/71283848
复制相似问题