保护模式1-段寄存器-基本属性
段寄存器是什么?
Segment Register 也可以称作 Selector Register
当我们用汇编读写某个地址时
MOV DWORD PTR DS:[0X00401000],EAX
我们读写的地址其实是DS.BASE+0x00401000
0x00401000被称为读写的有效地址
DS.BASE+0x00401000被称为线性地址,这里做了解即可
段寄存器有自己结构
段寄存器一共96位,但是可见部分只有16位
Struct SegMent
{
WORD Selector; //16位段选择子
WORD Attributes; //16位属性
DWORD Base; //32位基址
DWORD Limit; //32位段限长
}
其中不可见部分暂不理会,可见部分可以通过OD随便打开一个程序查看
其中红色部分就是段选择子Select
段寄存器 Select Attribute Base Limit
ES 002B 可读/可写 0 0xFFFFFFFF
CS 0023 可读/可执行 0 0xFFFFFFFF
SS 002B 可读/可写 0 0xFFFFFFFF
DS 002B 可读/可写 0 0xFFFFFFFF
FS 0053 可读/可写 0x7FFDE000 0xFFF
GS - - - -
为了验证段寄存器的属性:
Selector:
MOV AX,ES
这里的段选择子为16位,只能使用16位AX寄存器,不能使用32位EAX寄存器
EAX 0000002B
ECX 00FF0000
...
通过读取段寄存器,我们发现只能读取16位,这可见部分就是段选择子
Attribute:
int var = 0;
__asm
{
MOV AX,SS //SS可读,可写 CS可读,可执行
MOV DS,AX
MOV DWORD PTR DS:[var],EAX
}
执行上面代码发现并没有什么用,因为DS修饰的段指向了SS,SS段寄存器可读可写
如果把SS换成CS,就会发现访问错误,因为CS可读可执行,但是并不可写
Base:
int var = 0;
__asm
{
MOV AX,FS //不能换成DS
MOV GS,AX
MOV EAX,GS:[0]
MOV DWORD PTR DS:[VAR],EAX
//MOV DWORD PTR DS:[0X7FFDF000]
}
如果访问地址0会报内存访问错误0xC0000005错误这是常识,但是由于FS段寄存器的Base为0X7FFDF000
线性地址=FS.Base+有效地址 ---------------------- FS.0X7FFDF000+0x00000000
等于说直接访问了0X7FFDF000这个位置,虽然我们代码里写的是0
如果换成其他Base为0的寄存器就会发现内存访问错误
Limint:
int var = 0;
__asm
{
MOV AX,FS //不能换成DS
MOV GS,AX
MOV EAX,GS:[0x1000]
MOV EAX,DWORD PTR DS:[0X7FFDF000+0x1000]
MOV DWORD PTR DS:[var],EAX
}
0x0X7FFDF000+0x1000
FS段寄存器的段限长为FFF,但是我们读取的是0x1000位置的数据,这就能证明段的Limint真实存在