在x86中跳转到64位值

时间:2014-01-06 22:22:17

标签: assembly

[此代码适用于32位x86 Intel汇编程序。另外,请尝试遵循Xcode 5使用的汇编语法。汇编语言不是我的强项,我想尽量避免因为我不理解代码而导致的愚蠢错误。]

我正在尝试编写启动加载程序。我的内核的入口点位于0xFFFFFFFF之上(因为这个内核内核文件是以64位模式构建的)。现在,我有以下的汇编代码片段,取自我的启动加载器的源代码:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// startprog(phyaddr, arg)
// Start the program on protected mode where phyaddr is the entry point.
// Passes arg to the program in %eax.
//
_startprog:
  push    %ebp
  mov     %esp, %ebp

  mov     0xc(%ebp), %eax  // argument to program
  mov     0x8(%ebp), %ecx  // entry offset 
  mov     $0x28, %ebx      // segment
  push    %ebx
  push    %ecx

  // set up %ds and %es

  mov     $0x20, %ebx
  movw    %bx, %ds
  movw    %bx, %es

  lret

从C调用此代码,其中包含指向内核入口点和参数指针的指针。问题是,上面的代码假定入口点的地址适合32位指针。但是,我的内核的入口点不适合32位指针;它占用了原有大小指针的所有64位(如果你想知道,我不能简单地在32位模式下重建我的内核,否则我不会问这个问题)。在32位汇编中跳转到64位地址的最佳方法是什么?

感谢。 (如果您需要,可以使用sources for my kernelsources for my boot loader。)

1 个答案:

答案 0 :(得分:3)

首先需要在引导加载程序中切换到Long Mode(64位模式),只有然后才能跳转到内核。原因是指令指针(IP)在实模式下仅为16位宽,在虚拟保护地址模式下为32位宽,除长模式外,高32/48位被屏蔽掉。 / p>

很多“引导加载程序中的长模式”代码,例如this OSDev article on entering it without intermediate 32-bit mode。希望有所帮助。

如果您的内核不支持在长模式下调用,那么您唯一的选择是将其加载到4 GiB以下,因为上面的地址中不能运行任何32位代码。没有查看源代码(抱歉,它是凌晨1点26分,我需要明天工作),一些内核支持运行,比如说,他们的入口地址& 0x00FFFFFF之类的东西,在它们的最终操作模式设置之前。 (例如,MirBSD内核具有VMA和LMA 0xD0100120,但预计会跳转到0x00100120,然后设置分页本身以将其自身映射为高。