保護模式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真實存在