Review of Win32 Assembly (Memory Management part one)
Posted on 2009-08-21 23:04 alleoo 阅读(427) 评论(0) 收藏 举报保护模式下内存管理
by Yariv Kaplan
When the processor is running in protected-mode, two mechanisms are involved in the memory translation
process: Segmentation and Paging. Although working in tandem, these two mechanisms are completely
independent of each other. In fact, the paging unit can be disabled by clearing a single bit in an internal
processor register. In this case, the linear addresses which are generated by the segmentation unit pass
transparently through the paging unit and straight to the processor address bus.
当处理器运行在保护模式下时,内存寻址过程中会用到分段及分页两种机制,尽管工作流程中它们是串联的,但这两种机制并
无太多关联。事实上,分页功能单元是可以通过设置(清除)一个寄存器的bit位来实现启用和关闭的。如此,经过分段单元产
生的线性地址空间内地址就显示的传递给分页处理单元,从而最终形成物理地址放到处理器地址总线上。

Figure 1 - Protected-mode address translation process
Segmentation
分段机制
The role of the segmentation unit is the same as on the 8086 processor. It allows the operating system to divide programs into
logical blocks and place each block in a different memory region. This makes it possible to regulate access to critical sections of
the application and help identify bugs during the development process. The implementation of the segmentation unit on the 80386
(and above) is simply an extension of the old 8086 unit. It includes several new features such as the ability to define the exact
location and size of each segment in memory and set a specific privilege level to a segment which protects its content from
unauthorized access.
分段机制的作用和在8086处理器下是一样的。这允许操作系统能够将代码分成逻辑上的块而存储到不同的内存区域,
这使得对应用程序的某些关键块进行访问控制成为可能,而且能够使开发过程中引入的bug暴露出来。80386及之后
更先进的处理器使用的分段机制只是较老的8086处理器的扩展。它包括了一些新特性,如能够在内存中精确定义每
块的地址和大小, 能够对每个段设置特权级别,从而保护所存储的数据阻止未授权的访问。
Not only real-mode applications use segment registers for accessing memory. The same process takes place under
protected-mode. However, there are several differences which should be considered.
First, there is a slight change in terminology. Under protected-mode, segment registers receive the name Selectors
which reflects their new role in the memory translation process. Although still 16-bit in size,
their interpretation by the processor is inherently different.
Figure 2 presents the structure of a selector along with the various bit-fields which comprise it.
并不是只在实模式下应用程序才使用段寄存器访问内存的。在保护模式下也会用到。然而,必须注意到它们之间有
几个不同之处。第一就是术语方面的不同。保护模式下,段寄存器内存放的是选择子,选择子这个名字能反映出它
在寻址过程中的作用,尽管段寄存器也是16位的,但处理器解释其存储的内容的意义是不同的。图2表明的就是选择
子及其组成域的结构。

Figure 2 - Internal composition of a selector
Instead of shifting segment registers (selectors) four bits to the left and adding an offset (like in real-mode), the processor treats each selector as an index to a Descriptor Table.
并不象在实模式下段寄存器值左移四位加上偏移形成物理地址,此时它作为段描述符表的索引。
Descriptor Tables
段描述符表
Descriptor tables reside in system memory and are used by the processor to perform address translation. Each entry in a
descriptor table is 8 bytes long and represents a single segment in memory. A descriptor entry contains both a pointer to
the first byte in the associated segment and a 20-bit value which represents the size
of the segment in memory. Several other fields contain special attributes such as a privilege level and the
segment's type. Figure 3 presents the exact structure of a descriptor entry along with a description of each of its internal fields.
段描述符表位于系统内存区,它被用来进行地址转换。在段描述符表中每一个描述符项长度为8个字节代表内存中一个
段的信息。一个描述符项包含了向其相应段的入口地址(32bit),以及表示该段在内存中宽度的20bit的数据。
其它一些区域包含一些特殊参数如特权级别和段类型。图3所示的是段描述符的完整结构。

Figure 3 - Structure of a descriptor entry
Table 1 contains a complete list of all descriptor fields and their functionality.
|
Field |
Designated Role |
|
BASE |
Segment Base Address (32-bits) |
|
D/B |
Segment Size Bit When the descriptor entry describes a data segment, this bit is used to control the operation of |
|
DPL |
Descriptor Privilege Level (2-bits) 段描述符特权级 它定义了段的特权级别。保护模式下用来限制对段的访问。 |
|
G |
Granularity Bit |
|
LIMIT |
Segment Limit (20-bits) |
|
P |
Segment Present Bit 段存在位 该位表示该描述符描述的段是否存在于内存中。 此位被清零,此时如果指向该描述符的选择子被加载到段寄存器时就会引发段不存在异常。 它被用来通知操作系统任何企图访问由虚拟内存提供的内存段或者是未被申请却企图访问的内存段。 |
|
S |
Descriptor Type Bit |
|
Type |
Segment Type (4-bits) When the descriptor entry describes a data segment, this field determines the type of the segment: |
Since each selector points to a specific descriptor entry, there is a one to one relationship between selectors
and segments in memory. This concept is demonstrated in the following figure.
因为每一个选择子都指向一个特定的段描述符。所以选择子和线性空间中的段是一对一的关系,下图做了清淅的说明。

Figure 4 - Relationship between selectors and segments
As figure 5 shows, linear address calculation (which can be the physical address if paging is disabled) is done by using
the selector as an index to the descriptor table, getting the base address of the segment, and adding the offset.
如图5所示,线性地址的计算(如不启用分页机制就是物理地址)是由选择子做为索引找到描述符表,
然后在描述符表中拿到段的基地址,加上32位的偏移就形成最终的物理地址。

Figure 5 - Virtual to linear address translation
Two types of descriptor tables are used by the processor when working in protected-mode.
The first is known as the GDT (Global Descriptor Table) and is used mainly for holding descriptor entries
of operating system segments. The second type is known as the LDT (Local Descriptor Table) and contains entries
of normal application segments (although not necessarily). During initialization, the kernel creates a single GDT which
is kept in memory until either the operating system terminates or until the processor is switched back to real-mode.
实际在保护模式下处理器要用到两种类型的段描述符表。第一种被称之为全局段描述符表(GDT),它主要是用来
保存操作系统的段相应的描述符;第二种叫做局部段描述符表,它保存的是应用程序的段对应的描述符
(有时不是必须的)。操作系统初始化时,内核会在内存中创建一个GDT,它将一直存在于内存中(被使用)
直到退出操作系统或是处理器被切换到实模式。
Whenever the user starts an application, the operating system creates a new LDT to hold the descriptor entries which represent
the segments used by the new task. This makes it possible for the operating system to isolate each task's address space by
enabling a different LDT whenever a task switch occurs. Bugs and other errors in the application cannot affect other running
processes and are limited in scope to the currently mapped memory segments.
Note that not all operating systems behave exactly as described above (for instance, all Windows applications share
a single LDT). However, this is the recommended programming practice as offered by Intel.
When looking for a specific descriptor entry, the addressing unit in the processor uses the TI bit
(which is part of the selector) to decide which descriptor table should be used (the GDT or the currently active LDT).
Figure 6 shows this process in clarity.
每当用户开启一个应用程序,操作系统将为它创建一个新的LDT用于保存该任务的段所对应的描述符。
由此,当发生任务切换时,操作系统就可能通过切换到不同的LDT来实现隔离各个任务的地址空间。
当一个应用程序因其错误或缺陷致使其崩溃时就不会影响到其它正在运行的程序进程,
再者这些缺陷也被限止到一该任务的段空间中。
注意并不是所有操作系统都是按照如上的方式运行的(例如,所有的windows应用程序共享一个LDT),
但这是Intel 推荐的方式。
当查找某个特定的段描述符时,处理器的寻址单元使用TI标识位(选择子的一个组成部分)
来确定使用那个描述符表(GDT 或者当前激活任务LDT)。由图6示。

Figure 6 - The Table Indicator bit
浙公网安备 33010602011771号