x86实模式下的段大小 [英] Segment size in x86 real mode

查看:328
本文介绍了x86实模式下的段大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对实模式下的分段大小有一个疑问,因为分段的长度不能超过64K,但可以为实模式段也可以重叠,不相交或相邻.像BIOS那样,对于某些特定的保留区域,例如引导代码,视频缓冲区等,汇编程序是否需要执行类似的操作?

I have one doubt regarding the size of segments in real mode as they can't be more than 64K but can be less than that. My question is how these segment size and base address is initialized ? Like there are GDT's and LDT's in protected mode.Real mode segments can also overlapped,disjoint or adjacent.Like BIOS has some reserved area for specific things like boot code,video buffer etc does assembly programs need to do something like that ?

推荐答案

实模式下的段限制为64k,即使在386或更高版本的CPU上,您也可以通过前缀使用32位地址大小.例如在实模式下,mov ax, [edx + ecx*4]仍被限制为64 kiB的偏移量.

The segment limit in real mode is 64k, even on a 386 or later CPU where you can use 32-bit address-size via prefixes. e.g. mov ax, [edx + ecx*4] is still limited to offsets of 64 kiB in real mode.

如果超出此限制,则会引发#GP异常. (如果段为SS,则为#SS.

If you exceed this limit, it raises a #GP exception. (Or #SS if the segment was SS).

16位地址大小不能超过64k段限制,因为[bx + si]之类的寻址模式会以16位换行.因此,只有在实模式下使用0x67地址大小前缀(在386中添加)的代码才能遇到段限制. 8086不必检查限制,只需将Sreg << 4添加到寻址模式的偏移量中,即可将限制隐式地设置为64k.

16-bit address-size can't exceed 64k segment limits, because addressing modes like [bx + si] wrap at 16 bits. So only code using the 0x67 address-size prefix (added in 386) in real mode can run into segment limits. 8086 didn't have to check limits, just add Sreg << 4 to the offset from an addressing mode, making the limit implicitly 64k.

从最高可能地址的64k开始的段在8086上以1MiB环绕,如果禁用了A20,则在以后的CPU上环绕.否则,它们会超出1MiB延伸到FFFF:FFFF seg:off = 0x10ffef linear之类的地址.参见什么是细分以及如何在8086模式下解决它们?

Segments that start within 64k of the highest possible address wrap around at 1MiB on 8086, and on later CPUs if A20 is disabled. Otherwise they extend past 1MiB for an address like FFFF:FFFF seg:off = 0x10ffef linear. See What are Segments and how can they be addressed in 8086 mode?

如果切换到保护模式并设置段寄存器,则CPU会将段描述(基数+限制)保留在内部缓存中,即使切换回16位实模式也是如此.这种情况称为 虚幻模式 .

If you switch to protected mode and set a segment register, the CPU keeps the segment description (base + limit) cached internally, even across switching back to 16-bit real mode. This situation is called unreal mode.

以16位模式写入段寄存器只会将段基设置为value << 4,而不会更改限制,因此unreal模式对于CS以外的段来说在某种程度上是持久的. CS:EIP很特殊,尤其是当您需要避免从中断或其他情况返回时将EIP截断为16位时.看到该osdev Wiki链接.

Writing to a segment register in 16-bit mode only sets the segment base to value << 4 without changing the limit, so unreal mode is somewhat durable for segments other than CS. CS:EIP is special, especially if you need to avoid truncating EIP to 16 bits when returning from interrupts or whatever. See that osdev wiki link.

push /pop/call/ret使用SS:ESPSS:SP根据当前堆栈段描述符中的B标志;地址大小前缀仅影响push word [eax]push word [si]之类的东西.

push/pop/call/ret use SS:ESP or SS:SP according to the B flag in the current stack-segment descriptor; the address-size prefix only affects stuff like push word [eax] vs. push word [si].

在实模式下将值写入段寄存器时,将忽略GDT/LDT.该值直接用于设置缓存的段基础,而根本不用作选择器.

(每个段都是独立的;虚实模式不是像保护vs.实模式那样的实际模式; CPU处于实模式.例如,写入FS寄存器会使该段恢复为正常实模式行为,但是不会改变其他名称.这只是在实模式下使用具有较大限制的缓存段描述符的名称,因此您可以将32位地址大小用于更大的固定地址空间,通常使用base = 0和limit = 4G )

(Each segment is separate; unreal mode isn't an actual mode like protected vs. real; the CPU is in real mode. Writing the FS register, for example, puts that segment back into normal real-mode behaviour, but doesn't change the others. It's just a name for being in real mode with cached segment descriptors with larger limits, so you can use 32-bit address-size for a larger flat address space. Often with base=0 and limit=4G)

AFAIK,无法以实模式查询段的内部极限值. lsl 直接从内存中GDT/LDT中的描述符加载段限制值,而不是内部值(因此这不是您想要的),并且无论如何都无法在实模式下使用.

AFAIK, there's no way to query the internal limit value of a segment in real mode. lsl loads the segment-limit value directly from a descriptor in the GDT / LDT in memory, not from the internal value (so it's not what you want), and it's not available in real mode anyway.

请参阅对此答案的评论,以获取有关有意或无意地使分段脱离虚幻模式的更多详细信息.

See comments on this answer for more details about taking segments out of unreal mode intentionally or unintentionally.

支持286和386 CPU 一条LOADALL指令,该指令可以将分段限制设置为实际模式,但后来的CPU没有.评论者说SMM(系统管理模式)也许可以在现代x86上做类似的事情.

286 and 386 CPUs supported a LOADALL instruction which could set segment limits from real mode, but later CPUs don't have it. Commenters say that SMM (system management mode) may be able to do something similar on modern x86.

这篇关于x86实模式下的段大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆