假设我的API是从一个只能在实模式或大实模式下工作的系统调用的。我的API应该显示当前的系统模式。那怎么知道当前模式是实模式还是大实模式呢?
注意:
CR0
中的保护模式使能位被禁用,因此检查它没有任何区别。答案 0 :(得分:1)
如果执行此操作:
mov ebx, 0x10000
mov al, [ebx]
并获得#GP
,然后DS
的段描述符的原始限制为0xFFFF,这是正常实地址模式和虚拟8086模式的情况。
如果您没有从#GP
获得mov al, [ebx]
,则原始限制已扩展到0xFFFF以上(通常为0xFFFFFFFF,但不一定如此)。
顺便说一句,检查v86模式可以并且可能应该在尝试上述之前完成(如果主机操作系统没有正确反映处理程序的异常)。执行smsw
以获取cr0.pe
。它将在v86模式下设置为1,在实际地址模式下设置为0。直接使用cr0
阅读mov
将在v86模式下生成#GP
,这就是smsw
是首选方法的原因。
答案 1 :(得分:0)
在大实模式下,实模式地址别名会失败。让我们假设你处于大实模式,你的DS值为0x6000。由于已重新加载DS的描述符缓存(大实模式的定义),因此DS:0的物理地址不是0x60000。如果用另一个段寄存器命中0x60000,那么它将不是相同的存储单元。
所以这是一个食谱。在数据段中创建临时变量。请注意相对于DS的offset
。使用DS-1的值加载ES,更改变量的值,并查看是否在ES处获得相同的值:(offset
+ 0x10)。为了防止误报,请做两次。
这不会检测虚拟86模式。此外,如果ES通过缓存的描述符指向高内存,那么当您重新加载ES时,这将丢失。确保调用者代码不依赖于ES保持不变。
大实模式本身并不是CPU模式 - 没有寄存器位表示“我们现在处于真实状态”。它只是一种使用香草实模式的i386特定逻辑访问高内存的方法。上述程序仅检查DS是否已按此方式处理;根据实现,DOS扩展器可能已经通过ES描述符重新加载实现了大的真实,同时保留了DS vanilla。维基百科说,有时甚至CS也会以这种方式混淆,尽管由于中断,这是一个棘手的命题。
答案 2 :(得分:0)
在90年代早期,我们使用一种未记录的方法让我们在REAL模式下访问4Gig(现在可称为BIG REAL MODE)。方法是进入保护模式,将粒度位更改为1(表示4K粒度而不是1字节粒度)然后返回实模式并将所有段寄存器设置为0.然后可以使用ebx等访问4Gig的记忆。
因此,如果您正在讨论这个问题,请尝试进入保护模式并检查粒度位的设置。对不起,我所有的旧手册都在阁楼里。如果您需要这些信息,我可以将它们挖出来。