x86 中的 %cs 和 %eip 寄存器
概要:介绍 %cs(代码段寄存器)与 %eip(指令指针寄存器)的字长、作用与工作机制,并说明 CS:EIP 组合如何定位下一条指令,以及段内跳转与跨段跳转的区别。
在 x86 体系结构中,%cs 和 %eip 是两个极其关键的寄存器,它们像是一对“搭档”,共同决定了 CPU 接下来要执行哪一条指令。
1. %cs (Code Segment Register,代码段寄存器)
- 字长:16 位。
- 核心作用:它用来存放当前正在执行的代码段的基地址(在实模式下)或段选择子(在保护模式下)。
- 通俗理解:在内存中,程序是被分段存放的(比如代码段、数据段、堆栈段等)。
%cs就像是一个路牌,专门指向存放“程序代码”的那块区域的开头。 - 权限控制:在保护模式下,
%cs寄存器的最低两位(RPL,请求特权级)还决定了当前 CPU 的执行权限(比如是运行在内核态的 Ring 0,还是用户态的 Ring 3)。
2. %eip (Extended Instruction Pointer,扩展指令指针寄存器)
- 字长:32 位。(在 16 位时代叫
%ip,在 64 位时代叫%rip)。 - 核心作用:它用来存放下一条将要执行的指令在代码段内的偏移量(Offset)。
- 工作机制:
- 自动递增:CPU 每从内存中取走一条指令,
%eip的值就会自动增加,加上刚刚取走的那条指令的字节长度,从而指向紧接着的下一条指令。 - 被动修改:你不能用普通的
mov指令直接去修改%eip(比如mov %eax, %eip是非法的)。它只能通过跳转指令(jmp)、函数调用指令(call、ret)或中断操作来间接改变。
它们是如何协同工作的?(CS:EIP 机制)
CPU 要知道下一条去哪取指令,永远依靠的是 CS:EIP 这个组合。
- 定位物理地址:CPU 会把
%cs提供的“段基址”和%eip提供的“段内偏移量”结合起来。 - 在实模式下:物理地址 =
CS << 4 + EIP。 -
在保护模式下:CPU 会通过
%cs里的选择子去“全局描述符表 (GDT)”里查到代码段的基地址,再加上%eip里的偏移量,算出线性地址(最终映射到物理地址)。 - 执行流程:只要改变了
CS:EIP的值,CPU 的执行流就会发生跳转。 - 如果是段内跳转(比如同一个函数内的
if-else或while循环),%cs保持不变,只改变%eip。 - 如果是跨段跳转(比如不同特权级之间的切换,或者调用其他代码段的系统调用),则需要同时修改
%cs和%eip(通常被称为 Far Jump 或 Far Call)。
总结来说,%cs 决定了你在哪一栋楼(代码段)里,%eip 决定了你要去这栋楼的哪个房间(具体指令偏移)。没有它们,CPU 就不知道下一步该干什么。
留下评论