实模式
实模式是所有的 Intel x86 处理的初始的 16 比特操作模式,之所以在现代的 x86 处理器中存在实模式是为了与 80386 之前的处理器保持兼容。
1. 简介
所有现代的操作系统( Windows 、 Linux… )都运行在保护模式下,由于实模式存在很多限制和问题,比较老的运行在实模式下的操作系统(像 DOS )和程序,由于当时这有这一种模式可以使用,可以通过阅读一些文章,获得如何从实模式转换到保护模式。
注意:有一种模式叫做“虚拟的 8086 模式”,就是运行在保护模式下的操作系统来模拟实模式下的分段模型,以满足个人的应用,这将允许保护模式的操作系统仍然可以获得 BIOS 函数,只要需要的话。
1) 实模式的限制:
n 少于 1MB 的 RAM 可用。
n 没有基于硬件的内存保护( GDT ),也没有虚拟内存。
n 没有对执行的限制,任何用户程序都可以执行。
n 默认的 CPU 操作数长度只有 16bits 。
n AX , CX , DX 不是“通用”寄存器,例如,他们不能用于寻址
n 默认的内存地址模式不同,且功能比较小
n 现在的编译器不能产生兼容实模式的代码。
2) . 优势
n BIOS 函数执行在系统的 BIOS ,没有任何的事件下。
n BIOS 具有“驱动器”用来处理大多数的硬件。
3) . 通常的误解
程序员通常认为由于实模式默认是 16bits ,以致不能进入 32bit 的寄存器,这是不对的。
所有的 32bit 的寄存器( EAX,…… )仍是可用的,如果想用 32bit 的寄存器的话,只要通过简单的加入“ Operand Size Override Prefix ”( 0x66 )到任何指令的开始处,汇编器就会自动操作,
2. 内存寻址
在实模式下,只有 1MB 的可寻址的内存(包括高内存区域)。可以阅读 Detecting Memeory ( x86 )和 Memory Map(x86) 来决定有多少的内存可以使用,可用的内存将会是少于 1MB ,内存寻址时通过段偏移机制来进行的。
有 6 个 16bit 的段寄存器: CS 、 DS 、 ES 、 FS 、 GS 和 SS 。当使用段寄存器的时候,地址是通过下面的标记来给出的(其中“段”是一个在段寄存器中的值,“偏移”是一个在地址寄存器中的值)。如下:
然后,
段地址和偏移地址通过如下的等式计算得到物理地址
PhysicalAddress = Segment*16+Offset
这样, 12F 3:4B27 相对应的物理地址为 0x17A57 ,任何的物理地址可以以多种方式表示,通过不同的段地址和偏移地址,例如,物理地址 0x210 可以是 0020:0010,0000:0210 或 0021:0000
1) 堆栈
SS 和 SP 是 16bit 的段地址:偏移地址得到的 20bit 的物理地址(如上描述),它是当前堆栈的栈顶。堆栈存储 16bit 字,向下增长,同时必须字( 16bit )对齐,每一个程序使用 PUSH 、 POP 、 CALL 、 INT 或 RET 伪代码来使用,同时当 BIOS 处理任何硬件中断时,也需要使用。
2) 高内存区域
如果设置 DS (或任何段寄存器)为 0xFFFF ,所指地址为 16bytes 在 1MB 一下,如果把它当着基地址,偏移地址为 0x10 到 0xFFFF ,将获得物理内存地址为 0x100000 到 0x10FFEF ,这个(几乎是 16kB )的区域大于 1MB 以上,叫做实模式下的“高内存区域”。注意到,此时必须打开 A20 地址位使其工作。
3) 寻址模式
实模式默认情况下使用 16bits 的寻址模式,汇编程序员典型的熟悉 32bit 的寻址模式,所以需要做出调制——因为 16bit 寻址模式下可用的寄存器用于指针的更加的有限,典型的运行在实模式下的程序常被现在数 bytes 下可用,需要使用一个额外的 byte 用于 32bit 的寻址来代替
注意到,在实模式下,可以仍然使用 32bit 的寻址模式,在任何指令的开始,加入“ Address Size Override Prefix ” (0x67) ,汇编器就可以自动编译了,