assembly - 为什么mov不能设置CS,代码段寄存器,即使它可以设置其他?
问题描述
我需要知道使用 mov 指令直接加载代码段寄存器是否有任何限制。
这让我在从实模式切换到保护模式时感到震惊。我发现为了在代码段中放入正确的值,“跳转”指令用于设置正确的段。
那么这种跳转指令的使用是由于任何这样的限制吗?为什么我们不能直接将值加载到代码段中?
解决方案
设置 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
不是跳跃,这很奇怪。强迫你同时设置 CS 和 IPjmp
对我来说似乎很理智/正常。
相关:是否可以在 8086 汇编中操作指令指针?.
英特尔 8086 程序集中 CS 和 IP 寄存器的用途是什么?
请记住,386 保护模式是一种扩展;在实模式下,CS值直接用作段基 = cs<<4
。 加载具有相同基数的新描述符的用例是 386 的新用例(或者可能是 286 保护模式)。在此之前并没有真正的操作码mov cs, r/m16
或pop cs
操作码的用例,因此英特尔将这些指令编码保留用于其他用途。
通过不必支持mov cs, r/m
或pop cs
作为必须丢弃预取代码的跳转指令,这简化了未来的 CPU。
(在 8086 的一些早期版本中,确实存在,遵循与/其他段 regpop cs
相同的模式,并且它具有 opcode ,但英特尔明智地决定保留用作未来 x86 CPU 中多字节操作码的转义字节。 什么如果更改 CS 段寄存器会发生什么?(你会怎么做?))。push
pop
0x0f
0F
在保护模式下更改 CS 甚至比在实模式下更不常见(主流操作系统使用平面内存模式),因此绝对没有必要开始支持mov
CS。 jmp far
工作得很好,实际上更好,因为您不需要确保IP
/EIP
相对于段基础的偏移量在之前/之后是相同的。
推荐阅读
- pytorch - 给定前馈步骤中张量的索引版本,pytorch 如何执行反向微分?
- reactjs - 将 CSV 数据添加到 React 应用程序,而文件不会在构建中结束
- r - 如何使用 R 中的 copula 函数计算条件概率?
- java - 损坏的表值,我该如何解决?
- javascript - 如何访问嵌入式对象?
- reactjs - Reack Hook:useEffect() 被调用两次,首先是一个空数组,然后是数据库中的值
- flutter - 如何克隆从 Flutter/Dart 中的父小部件传递的对象
- tensorflow - 给定kdtree提供的距离和索引,如何实现grapy的邻接?
- html - 如何在输入类型号时禁用“onchange()”
- c++ - 学校 C++ 项目