小编Ale*_*der的帖子

在Linux内核中从真实模式转换为保护模式

我目前正在研究操作系统的低级组织.为了实现我想要了解Linux内核是如何加载的.

我无法理解的是从16位(实模式)到32位(保护模式)的转换.它发生在这个文件中.

protected_mode_jump函数对稍后执行的32位代码执行各种辅助计算,然后启用调节器中的PECR0

    movl    %cr0, %edx
    orb $X86_CR0_PE, %dl    # Protected mode
    movl    %edx, %cr0
Run Code Online (Sandbox Code Playgroud)

然后执行长跳转到32位代码:

    # Transition to 32-bit mode
    .byte   0x66, 0xea      # ljmpl opcode
2:  .long   in_pm32         # offset
    .word   __BOOT_CS       # segment
Run Code Online (Sandbox Code Playgroud)

据我所知in_pm32,32位函数的地址在下面声明protected_mode_jump:

    .code32
    .section ".text32","ax"
GLOBAL(in_pm32)
    # some code
    # ...
    # some code
ENDPROC(in_pm32)
Run Code Online (Sandbox Code Playgroud)

__BOOT_CS扇区基是0(GDT被设定预先这里),因此这意味着,偏移应该是基本上绝对地址in_pm32的功能.

这就是问题所在.在机器代码生成期间,汇编器/链接器不应该知道in_pm32函数的绝对地址,因为它不知道在实模式下它将在内存中加载的位置(各种引导加载程序可以占用不同的空间量,以及实模式内核)在引导加载程序之后加载).

此外,链接器脚本(setup.ld在同一文件夹中)将代码的原点设置为0,因此看起来in_pm32地址将是从实模式内核开始的偏移量.它应该可以正常使用16位代码,因为CS寄存器设置正确,但是当发生长跳转时,CPU已经处于保护模式,因此相对偏移不应该起作用.

所以我的问题:.byte …

x86 assembly real-mode protected-mode linux-kernel

6
推荐指数
1
解决办法
555
查看次数

标签 统计

assembly ×1

linux-kernel ×1

protected-mode ×1

real-mode ×1

x86 ×1