【问题标题】:Doing a indirect far jump/call in protected mode在保护模式下进行间接远跳转/调用
【发布时间】:2011-01-27 04:36:59
【问题描述】:

如何在保护模式下执行间接远跳转/调用?首先,我认为这样做是允许的:

jmp 0x10:eax;

(不用担心段选择器。我的 GDT 的第二个条目是有效的代码段)

但是当 nasm 组装它时,这是一个语法错误。查看Intel(指令集参考)手册的Book 2a,只能使用jmp ptr16:32,其中ptr16:32是一个立即数,或者使用jmp m16:32,其中m16:32是一个内存位置包含 48 位跳转地址(即 16:32)。

现在我尝试这样编码:

mov dword[ds:jumpaddress_offset],eax
; or just dword[jumpaddress_offset],eax
mov word[ds:jumpaddress_sel],0x10;
; or just mov word[ds:jumpaddress_sel],0x10;
jmp dword far [dword ds:jumpaddress];
...
jumpaddress:
jumpaddress_sel dw 0
jumpaddress_offset dd 0

它组装成功,但是当我尝试运行它时,处理器出现一般保护错误并重新启动。我不知道发生了什么。

我假设编码是这样的:

(例如我想使用间接跳转跳转到0x10:0x8010)

dw 0x10
dd 0x8010

这可能有什么问题? 是不是应该用小端编码48位内存值? 应该这样编码吗?

;0010 0000 8010
dd 0x10,0x80,0,0,0x10,0

最后一个我还没试过。

【问题讨论】:

    标签: assembly x86 osdev


    【解决方案1】:

    一个常用的技巧是使用远距离模拟跳跃,例如:

    push 0x10
    push eax
    retf
    

    【讨论】:

    • 我已经解决了。 48 位地址应该用 little endian 编码,即先定义 32 位偏移量,然后定义 16 位段选择器。好吧,你可以做到这一点,使用间接跳转也有一些优点.
    【解决方案2】:

    x86 处理器使用 little-endian 模式。与此一致,目标的偏移量在内存中的段之前。对于您的示例,您应该使用:

    dd 0x8010 ;远跳的偏移量

    dd 0x10 ; 远跳段,由于对齐原因扩展为双字

    ;------------------

    db 0x10, 0x80, 0, 0, 0x10, 0, 0, 0 ;也可以。

    您可能仍会获得特权异常。为了使代码能够工作,目标代码段必须与源代码段具有相同的权限级别。

    主要来源:Robert L. Hummel 的处理器和协处理器

    【讨论】:

      猜你喜欢
      • 2017-01-27
      • 2012-10-10
      • 2022-09-25
      • 2012-02-26
      • 2016-08-15
      • 2014-10-05
      • 2015-11-03
      • 2013-02-21
      • 2020-06-08
      相关资源
      最近更新 更多