在保护模式下进行间接远跳转/调用

4
在保护模式下如何执行间接远跳转/调用?我最初认为可以这样做:
jmp 0x10:eax;

不用担心段选择器,我的GDT的第二项是一个有效的代码段。

但是当nasm将其汇编时,会出现语法错误。查看英特尔手册(指令集参考)的书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

我还没有尝试过做最后一个。


相关内容,在16位模式下相同:NASM实模式中的far跳转/ far调用和ASM代码约定。同时,在实模式下跳转到远地址 - Peter Cordes
2个回答

5

经常使用的技巧是使用远程 ret 来模拟跳转,例如:

push 0x10
push eax
retf

1
我已经解决了。48位地址应该以小端方式编码,即先定义32位偏移量,然后是16位段选择器。嗯,既然你能做到这一点,使用间接跳转也有一些优势。 - prinzrainer

1

x86处理器使用小端模式。为此,在内存中,目标的偏移量在段之前。对于您的示例,您应该使用:

dd 0x8010; 远跳转的偏移量

dd 0x10; 远跳转的段,为了对齐而扩展为双字

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

db 0x10、0x80、0、0、0x10、0、0、0; 也可以使用。

您可能仍会收到特权异常。为使代码正常工作,目标代码段必须与源段具有相同的特权级别。

原始来源:Robert L. Hummel的处理器和协处理器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接