You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

进入CPU保护模式后的远跳转及相关技术疑问

保护模式切换相关技术疑问解答

1. 什么是far jump?

远跳转(far jump)是x86架构下的一种跳转指令,和普通近跳转的核心区别是:它会同时修改代码段寄存器CS和指令指针寄存器IP/EIP,而近跳转只会修改IP/EIP,CS保持不变。

实模式下,远跳转格式是段值:偏移量,用于跨16位段跳转;进入保护模式后,这里的“段值”变成段选择子,用来指定全局描述符表(GDT)或局部描述符表(LDT)中的某个段描述符,CPU通过该描述符获取段的基地址、限长、权限等信息,再结合偏移量计算最终物理地址。

你代码里的jmp CODE_SEG:start_protected_mode就是典型的远跳转,它会把CS设置为CODE_SEG对应的段选择子,同时将EIP指向start_protected_mode的偏移地址。

2. 切换至保护模式对CPU具体有哪些作用?

切换到保护模式后,CPU会开启实模式不具备的核心特性,主要包括:

  • 地址空间扩展:从实模式的1MB寻址范围,拓展到32位保护模式下的4GB(64位保护模式范围更大),突破实模式的内存限制。
  • 分段与分页机制:通过GDT/LDT的段描述符实现内存分段管理,还可开启分页机制实现虚拟内存,提供灵活的地址转换和内存隔离能力。
  • 特权级保护:引入Ring0~Ring3四个特权级,不同层级代码拥有不同权限,比如仅Ring0(内核级)能执行修改控制寄存器的指令,有效隔离用户态与内核态代码,提升系统安全性。
  • 32位指令集支持:可使用32位寄存器(如EAX、EBX)和32位寻址方式,充分发挥CPU的32位运算能力,而实模式仅支持16位寄存器与寻址。
  • 内存访问校验:每次内存访问都会通过段描述符检查权限、地址是否超出段限长,非法访问会触发CPU异常,避免错误代码破坏系统。

3. CODE_SEG是什么?为何要与start_protected_mode偏移量配合使用?能否直接使用普通跳转jmp start_protected_mode?

CODE_SEG的定义

CODE_SEG是你定义的常量,等于code_descriptor - GDT_start,即GDT中代码段描述符相对于GDT起始地址的字节偏移量。由于GDT中每个段描述符占8字节,这个偏移量是8的整数倍,对应段选择子的高13位就是该描述符在GDT中的索引,低3位默认为0(TI=0表示使用GDT,RPL=0表示最高特权级),所以CODE_SEG本质是指向GDT中代码段描述符的段选择子。

为什么要配合偏移量使用

在你置位CR0的PE位(第0位)后,CPU已进入保护模式,但CS寄存器仍保留实模式下的段值,未更新为保护模式的段选择子。远跳转CODE_SEG:start_protected_mode有两个关键作用:

  1. 更新CS寄存器:将CS设置为CODE_SEG对应的段选择子,让CPU后续通过GDT中的代码段描述符解析代码地址。
  2. 刷新指令流水线:实模式与保护模式的指令解码规则完全不同,远跳转可强制清空CPU指令流水线,避免CPU继续按实模式规则解码保护模式下的指令,防止执行错误。

能否用普通跳转?

不能直接使用普通的jmp start_protected_mode。普通跳转是近跳转,仅修改EIP,不会更新CS。此时CS仍是实模式段值,CPU在保护模式下会将其当作段选择子去GDT查找描述符,但实模式段值通常对应GDT的NULL描述符(GDT第一个描述符必须为NULL),这会直接触发CPU异常,导致系统崩溃。

CPU会自动识别吗?

CPU不会自动识别bootloader代码的位置。置位CR0仅开启保护模式,但段寄存器内容不会自动更新,必须通过远跳转手动将CS设置为正确的段选择子,才能让CPU按保护模式规则正确寻址到start_protected_mode的代码。


内容的提问来源于stack exchange,提问作者alireza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:15:36