段寄存器是什么?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随便打开一个程序查看 其中红色部分就是段选择子Selector 段寄存器 Selector 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 0000002BECX 00FF0000 通过读取段寄存器,我们发现只能读取16位,这可见部分就是段选择子 -------------------------------------------------------------------------------------- ---Attribute 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]} 执行上面代码发现并没有什么用,因为DS修饰的段指向了SS,SS段寄存器可读可写 如果把SS换成CS,就会发现访问错误,因为CS可读可执行,但是并不可写 -------------------------------------------------------------------------------------- ---Base int var = 0;__asm{MOV AX,FS //不能换成DSMOV GS,AXMOV 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 //不能换成DSMOV GS,AXMOV EAX,GS:[0x1000]MOV EAX,DWORD PTR DS:[0X7FFDF000+0x1000]MOV DWORD PTR DS:[var],EAX} 0x0X7FFDF000+0x1000 FS段寄存器的段限长为FFF,但是我们读取的是0x1000位置的数据,这就能证明段的Limint真实存在 -------------------------------------------------------------------------------------- 通过以上4个小实验,证明了一个完整的段描述符具有这4个基本属性 |
|