【问题标题】:Why can't mov set CS, the code segment register, even though it can set others?为什么mov不能设置CS,代码段寄存器,即使它可以设置其他?
【发布时间】:2019-02-28 14:54:02
【问题描述】:

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

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

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

【问题讨论】:

  • 您不能直接使用 MOV 指令修改 CS,但可以使用 FAR JMP 或 FAR CALL 设置它,在其中指定要加载到 CS 中的段和标签跳到。您也可以使用 FAR CALL。还有一些其他更复杂的方式我不会提及。 FAR JMP 的语法取决于您使用的汇编程序(您从未提到过)
  • 如果你查看MOV 的指令集参考,它有这样的语句MOV 指令不能用于加载CS 寄存器。尝试这样做会导致无效的操作码异常 (#UD)。要加载 CS 寄存器,请使用 far JMP、CALL 或 RET 指令

标签: assembly x86 memory-segmentation


【解决方案1】:

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

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

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

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

相关:Is it possible to manipulate the instruction pointer in 8086 assembly?.
What is the purpose of CS and IP registers in Intel 8086 assembly?


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

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

(在 8086 的一些早期版本中,pop cs 确实存在,遵循与其他段 reg 的 push/pop 相同的模式,并且它的操作码为 0x0f,但英特尔明智地决定保留 @987654342 @ 用作未来 x86 CPU 中多字节操作码的转义字节。What would happen if the CS segment register is changed? (And how would you do so?))。


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

【讨论】:

  • mov cs, reg 在 286+ 中绝对无效的一件事是 cs 在 PM 中包含 CPL。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 2020-02-14
相关资源
最近更新 更多