首页 > 解决方案 > 为什么mov不能设置CS,代码段寄存器,即使它可以设置其他?

问题描述

我需要知道使用 mov 指令直接加载代码段寄存器是否有任何限制。

这让我在从实模式切换到保护模式时感到震惊。我发现为了在代码段中放入正确的值,“跳转”指令用于设置正确的段。

那么这种跳转指令的使用是由于任何这样的限制吗?为什么我们不能直接将值加载到代码段中?

标签: assemblyx86memory-segmentation

解决方案


设置 CS 将一个跳跃,因为代码提取发生在 CS:IP(或 CS:RIP/EIP)中。

这样做是有道理的,仅限于jmp far//call farret far其他控制转移指令。

在不更改 IP 的情况下更改 CS 会很奇怪:在假设指令之后执行的下一条指令mov cs, ax将是new_CS_base:old_IP+2(因为mov cs,ax如果不使用操作数大小前缀,则长度为 2 个字节。)

当然,您可以进行设置,使代码相对于两个不同的段基础具有相同的 IP 偏移量,但事实pop cs是跳跃而pop ds不是跳跃,这很奇怪。强迫你同时设置 CS 和 IPjmp对我来说似乎很理智/正常。

相关:是否可以在 8086 汇编中操作指令指针?.
英特尔 8086 程序集中 CS 和 IP 寄存器的用途是什么?


请记住,386 保护模式是一种扩展;在实模式下,CS直接用作段基 = cs<<4加载具有相同基数的新描述符的用例是 386 的新用例(或者可能是 286 保护模式)。在此之前并没有真正的操作码mov cs, r/m16pop cs操作码的用例,因此英特尔将这些指令编码保留用于其他用途。

通过不必支持mov cs, r/mpop cs作为必须丢弃预取代码的跳转指令,这简化了未来的 CPU。

(在 8086 的一些早期版本中,确实存在,遵循与/其他段 regpop cs相同的模式,并且它具有 opcode ,但英特尔明智地决定保留用作未来 x86 CPU 中多字节操作码的转义字节。 什么如果更改 CS 段寄存器会发生什么?(你会怎么做?))。pushpop0x0f0F


在保护模式下更改 CS 甚至比在实模式下更不常见(主流操作系统使用平面内存模式),因此绝对没有必要开始支持movCS。 jmp far工作得很好,实际上更好,因为您不需要确保IP/EIP相对于段基础的偏移量在之前/之后是相同的。


推荐阅读