(线性地址),第四栏为段的限长 ,第五栏为段描述符的特权级,
第六栏标志对应段是否存在于内存中, 第七栏表示段的访问权限。
可以看出,这些段的基地址与DOS下的常用内存段完全吻合,并且均为16位的数据段,
限长为64K(0XFFFF),供应用
程序访问,都存在于内存中,可读写。实践证明,这些段
就是D OS的常用内存段,也就是说, 这里的线性地址即为物理地址。因此,可以用这
些段选择符对相应的物理内存进行访问。
从
程序运行的健壮性考虑,不应该直接应用上述段选择符,而应该用GetThreadSelec
torEntry()函数得到欲访问物理内存对应的段选择符,该API函数的原型定义为
BOOL GetThreadSelectorEntry (
HANDLE hThread,
// handle of thread that contains selector
DWORD dwSelector,
// number of selector value to look up
LPLDT_ENTRY lpSelectorEntry
// address of selector entry structure
);
其中,LDT_ENTRY的结构定义如下
typedef struct _LDT_ENTRY { // ldte
WORD LimitLow;
WORD BaseLow;
union {
struct {
BYTE BaseMid;
BYTE Flags1;
BYTE Flags2;
BYTE BaseHi;
} Bytes;
struct {
DWORD BaseMid : 8;
DWORD Type : 5;
DWORD Dpl : 2;
DWORD Pres : 1;
DWORD LimitHi : 4;
DWORD Sys : 1;
DWORD Reserved_0 : 1;
DWORD Default_Big : 1;
DWORD Granularity : 1;
DWORD BaseHi : 8;
} Bits;
} HighWord;
} LDT_ENTRY, *PLDT_ENTRY;
用下面的代码可以得到基地址为BASE_DESIRED,限长为0XFFFF的
内存段对应的段选择符:
extern CLDTApp theApp;
WORD wSelector; // 内存段对应的段选择符
LDT_ENTRY ldtEntry;
DWORD base, baseMid, baseHigh;
DWORD limit, limitHigh;
for ( WORD sel = 7; sel <= 0xffff; sel +=8 ) {
if (::GetThreadSelectorEntry ( theApp.m_hThread,
DWORD ( sel ), &ldtEntry ) ) {
baseMid = ldtEntry . HighWord . Bytes . BaseMid;
baseMid <<= 16;
baseHigh = ldtEntry . HighWord . Bytes . BaseHi;
baseHigh <<= 24;
base = ldtEntry . BaseLow + baseMid +
baseHigh;
limitHigh = m_ldtEntry . HighWord . Bits . LimitHi;
limitHigh <<= 24;
limit = limitHigh + m_ldtEntry . LimitLow;
&