assembly 如何在MASM中编写远绝对值JMP/CALL指令?

pvabu6sv  于 2023-01-05  发布在  其他
关注(0)|答案(4)|浏览(216)

如何使用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)?

hgncfbus

hgncfbus1#

有一种方法可以做到这一点,但是您需要使用MASM的/omf开关,以便它生成OMF格式的目标文件。这意味着目标文件需要与OMF兼容的链接器链接,如Microsoft的旧分段链接器(而不是其当前的32位链接器)。
要做到这一点,你需要使用MASM的一个很少使用和不被很好理解的特性,SEGMENT指令的ATaddress属性。`AT`属性告诉链接器段位于内存中的一个固定段落地址,如address``所示。它还告诉链接器丢弃段,这意味着段的内容不被使用。这也是为什么必须使用/omf开关的原因。MASM的默认对象文件格式PECOFF不支持这个。
AT属性为您提供了要跳转到的地址的段部分。要获取偏移部分,您只需在段内使用LABEL指令。结合ORG指令,您可以在特定段的特定偏移处创建标签。然后,您只需在JMP或CALL指令中使用此标签。
例如,如果要跳转到BIOS重置例程,可以执行以下操作:

bios_reset_seg SEGMENT USE16 AT 0ffffh
bios_reset LABEL FAR
bios_reset_seg ENDS

_TEXT SEGMENT USE16 'CODE'
    jmp bios_reset
_TEXT ENDS

或者,如果要调用入口点位于0000:7E00的 Boot 加载程序的第二阶段部分:

zero_seg SEGMENT USE16 AT 0
    ORG 7e00h
second_stage LABEL FAR
zero_seg ENDS

_TEXT SEGMENT USE16 'CODE'
    call second_stage
_TEXT ENDS
cwtwac6a

cwtwac6a2#

您是否考虑过使用__emit伪指令?
https://msdn.microsoft.com/en-us/library/1b80826t.aspx
我曾经不得不使用内联汇编来编写一个远跳转,我记不起远跳转的操作码,但是你可以这样做

__emit      0eah
__emit      0
__emit      0
__emit      0
__emit      0
__emit      8h
__emit      0
idv4meu8

idv4meu84#

我一直在测试与MASM 6.15这段代码,我想这可以帮助你。

.model small
    .386
    .stack 100h

    .DATA
     Message    DB  'hello','$'
     JMPPOS DB  78h,56h,34h,12h  ;the address to be jumped to  1234:5678

    .code
    .startup

     JMP  dword  ptr [JMPPOS]

    .exit
    END

相关问题