如何使用MASM编写远绝对JMP或CALL指令?具体来说,如何让它使用EA和CA操作码发出这些指令,而不是使用DB或其他数据指令手动发出它们?
例如,考虑跳转到 Boot 扇区中的BIOS重置入口点FFFF:0000的情况,如果我使用NASM,我可以用一个简单的方法在一条指令中编写此代码:
jmp 0xffff:0
对于GNU汇编程序,语法不那么明显,但下面的代码可以完成这项工作:
jmp 0xffff, 0
然而,当我尝试使用MASM的明显解决方案时:
jmp 0ffffh:0
出现以下错误:
t206b.asm(3) : error A2096:segment, group, or segment register expected
我试图避免的变通方法
在MASM中,我可以使用许多可能的变通方法,如以下任何一种:
手动汇编指令,手动发出机器码:
DB 0EAh, 0, 0, 0FFh, 0FFh
使用远间接跳转:
bios_reset DD 0ffff0000h
...
jmp bios_reset ; FF 2E opcode: indirect far jump
或者将地址压入堆栈,然后使用远RET指令“返回”到它:
push 0ffffh
push 0
retf
但是,我是否可以使用实际的JMP指令并让MASM生成正确的操作码(EA)?
4条答案
按热度按时间hgncfbus1#
有一种方法可以做到这一点,但是您需要使用MASM的
/omf
开关,以便它生成OMF格式的目标文件。这意味着目标文件需要与OMF兼容的链接器链接,如Microsoft的旧分段链接器(而不是其当前的32位链接器)。要做到这一点,你需要使用MASM的一个很少使用和不被很好理解的特性,
SEGMENT
指令的AT
address属性。`AT`属性告诉链接器段位于内存中的一个固定段落地址,如
address``所示。它还告诉链接器丢弃段,这意味着段的内容不被使用。这也是为什么必须使用/omf
开关的原因。MASM的默认对象文件格式PECOFF不支持这个。AT
属性为您提供了要跳转到的地址的段部分。要获取偏移部分,您只需在段内使用LABEL指令。结合ORG指令,您可以在特定段的特定偏移处创建标签。然后,您只需在JMP或CALL指令中使用此标签。例如,如果要跳转到BIOS重置例程,可以执行以下操作:
或者,如果要调用入口点位于0000:7E00的 Boot 加载程序的第二阶段部分:
cwtwac6a2#
您是否考虑过使用__emit伪指令?
https://msdn.microsoft.com/en-us/library/1b80826t.aspx
我曾经不得不使用内联汇编来编写一个远跳转,我记不起远跳转的操作码,但是你可以这样做
3npbholx3#
这在MASM中是不可能的。请参阅以下链接中的文章:
https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/24965
idv4meu84#
我一直在测试与MASM 6.15这段代码,我想这可以帮助你。