Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么在进入保护模式后,预取队列应该失效?_Assembly_X86 - Fatal编程技术网

Assembly 为什么在进入保护模式后,预取队列应该失效?

Assembly 为什么在进入保护模式后,预取队列应该失效?,assembly,x86,Assembly,X86,《英特尔开发人员手册》建议,在切换到保护模式后,我们会在MOV CR0指令更改执行流并序列化处理器后立即执行JMP或CALL指令。其目的是使预取队列无效,如第9章第9.10.2节的代码示例所示,START.ASM清单,第174-186行: 174 ; enter protected mode 175 MOV EBX,CR0 176 OR EBX,PE_BIT 177 MOV CR0,EBX 178 179 ; clear prefetch queue 180 JMP CLEAR_LABEL 18

《英特尔开发人员手册》建议,在切换到保护模式后,我们会在MOV CR0指令更改执行流并序列化处理器后立即执行JMP或CALL指令。其目的是使预取队列无效,如第9章第9.10.2节的代码示例所示,
START.ASM清单
,第174-186行:

174 ; enter protected mode
175 MOV EBX,CR0
176 OR EBX,PE_BIT
177 MOV CR0,EBX
178
179 ; clear prefetch queue
180 JMP CLEAR_LABEL
181 CLEAR_LABEL:
182
183 ; make DS and ES address 4G of linear memory
184 MOV CX,LINEAR_SEL
185 MOV DS,CX
186 MOV ES,CX

我们为什么要进行这样的操作?队列中的代码不是保持不变吗?因为这样的跳转根本不会改变任何标志或段,除了使预取队列中的当前数据无效以再次重新加载相同的内容之外?

因此,我找到了目的:根据表9-5,该表描述了STARTUP.ASM中的主要初始化步骤:

跳转到清除实模式指令队列附近


实际上,仅用于重新加载指令队列,因此早期的reala模式指令将替换为受保护模式指令。

请注意,它应该是一个跳转,其主要目的是加载
CS
。奇怪的是,手册使用了近跳跃。表9-4甚至这样说:
近跳转以清除实模式指令队列
是的,远跳转在iret之后执行。但是,建议在切换到保护模式后立即使用近跳转。预取队列中的指令也可能被预先编码,因此跳转可能会更改指令的解释。但是你可以像Jester说的那样,在加载CS的同时加载一个跳远,这通常是你想要立即进入保护模式的,这样你就可以切换到32位代码段。不,这是一个不同的跳远,在进入保护模式而不是近跳转后立即执行的操作,将CS中的值从原来的实模式值更改为32位环0代码选择器。英特尔手册中给出的示例并不反映正常做法。这是一个在处理器复位后不久将在引导ROM中使用的代码示例,而不是在操作系统初始化代码中。它假设CS加载的基址为0FFFF0000h,重置后的基址为0FFFF0000h,在实模式下不可能加载到CS中。@MichaelPetch Yah,在实际的80286或80386上,您可以使用LOADALL指令加载具有0FFFFFF0000H的CS基址。没有其他CPU支持它,尽管我认为至少有一些BIOS通过使用保护模式或系统管理模式加载选择器缓存来模拟这些指令。