assembly 为什么mov不能设置代码段寄存器CS,尽管它可以设置其他寄存器?

ct3nt3jp  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(264)

我需要知道使用mov指令直接加载代码段寄存器是否有任何限制。
这让我在经历从真实的模式到保护模式的切换时感到震惊。我发现,为了在代码段中放入正确的值,“跳转”指令被用来设置正确的段。
那么,这种跳转指令的使用是不是由于任何这样的限制?为什么我们不能直接把一个值加载到代码段中?

cwdobuhd

cwdobuhd1#

设置CS将一个跳转,因为代码获取是从CS:IP(或CS:RIP/EIP)发生的。
这样做仅限于jmp far/call far/ret far和其他控制传输指令是有意义的。
更改CS而不更改IP会很奇怪:在假设的mov cs, ax指令之后执行的下一条指令将是new_CS_base:old_IP+2(因为如果不使用操作数大小前缀,mov cs,ax的长度为2个字节)。
当然,你可以设置一些东西,这样你就可以在相对于两个不同的段基的相同IP偏移量处有代码,但是pop cs是一个跳转,而pop ds不是,这一事实很奇怪。
相关:是否可以在8086汇编中操作指令指针?
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作为跳转指令,这些指令必须丢弃预取的代码。
(In 8086的某些早期版本X1 M14 N1 X确实存在,遵循与其它段寄存器的X1 M15 N1 X/X1 M16 N1 X相同的模式,并且它具有操作码X1 M17 N1 X,但Intel明智地决定保留0F,以便在未来的x86 CPU中用作多字节操作码的转义字节。(你会怎么做?))
在保护模式下更改CS甚至比在真实的模式下更不常见(主流操作系统使用平面内存模型),因此完全没有必要开始支持mov到CS。jmp far工作得非常好,事实上更好,因为您不需要确保IP/EIP相对于段基的偏移在之前/之后相同。
正如Margaret所指出的,CS选择器的低2位是286或386保护模式下的当前特权级别(就像在x86-64长模式下),所以通常只有当你想执行不同的代码,而不是继续执行下一个代码时,才会这样做。这种特殊情况通常只有在从真实的模式转换到保护模式时才会出现,您可能希望加载CS以进入32位模式,而根本不改变代码获取的来源。但是,更改CS本身将更新CS基址,因此即使允许mov cs, reg也不会使这变得更容易。

相关问题