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