欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

保护模式1-段寄存器-基本属性

程序员文章站 2022-06-08 19:17:49
...

  • 段寄存器是什么?
  • Segment Register 也可以称作 Selector Register
    当我们用汇编读写某个地址时
MOV DWORD PTR DS:[0X00401000],EAX

我们读写的地址其实是DS.BASE+0x00401000

0x00401000被称为读写的有效地址
DS.BASE+0x00401000被称为线性地址,这里做了解即可

段寄存器有自己结构
保护模式1-段寄存器-基本属性
段寄存器一共96位,但是可见部分只有16位

Struct SegMent
{
	WORD Selector;     //16位段选择子
	WORD Attributes; //16位属性
	DWORD Base;     //32位基址
	DWORD Limit;    //32位段限长
}

其中不可见部分暂不理会,可见部分可以通过OD随便打开一个程序查看
保护模式1-段寄存器-基本属性其中红色部分就是段选择子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真实存在