一、x86體系結構的發展歷史:
1.常見處理器:
- inter:pc主流的處理器;
- AMD:部分pc電腦;
- arm:主要用於手機和平板等;
- ppc,mips:主要用於一些智能眼鏡、只能手錶等智能可穿戴設備。
2.CPU位數含義:
CPU的位數代表着CPU的計算能力,即就是ALU的計算能力,即ALU一次能夠計算的最大寬度,最長的字節長度,也就是做加法。
CPU位數 == ALU的寬度,ALU需要從寄存器取數據,寄存器數據來自數據總線,也就是:
CPU位數 == ALU的寬度 == 數據總線的條數。
地址總線的條數代表:可以訪問的地址範圍,假設地址總線16條,可以訪問的最大地址爲2^16
3.x86體系開創過程:
- x86體系始於8086,實際上真正意義上的32位的x86體系從80386開始的,80186、80286都是過渡階段;
二、8086地址映射簡介:實模式
1.訪問過程:
- 地址總線:20條(可訪問最大地址爲2^20,即1M)
- 數據總線:16條(總線上數據最大能傳遞2字節寬度的數據)
我們發現,數據總線中無法存放20位的地址,因爲數據總線最大寬度爲16位,此時引入4個16位的寄存器:IP寄存器存放地址的偏移量
- CS:code section 指令寄存器
- DS:data section 數據寄存器
- SS:stack section 堆棧寄存器
- ES:expand section 擴展寄存器
8086將物理內存劃分爲不同的段,正如寄存器名一樣,指令段、數據段、堆棧段、擴展段等。
此時,規定每個內存段的起始地址爲16的倍數,[16,2^16],然後將每個段的起始地址保存在對應的寄存器中,但是由於寄存器是16位的,地址都是20位的。
num % 16 == 0
一個數字可以被16整除,二進制的低四位全部爲0,只需要將內存段的地址的高16位保存在寄存器中
即DS>>4,去掉低4位
所以,最終寄存器中保存的都是不是真正的段起始地址,而是段起始地址的高16位。
假設訪問數據段的一個變量,過程如下
- 訪問DS寄存器,獲得數據段的起始地址;
- 將寄存器中獲得值左移4位,DS<<4,恢復成20位的地址;
- 最後,加上該數據在內存段上的偏移量IP
數據的最終地址: DS<<4 + IP
其中,IP又被稱爲偏移量、偏移地址、邏輯地址
這裏的分段是指對物理內存的分割,與段頁式管理沒聯繫,段頁式管理式在有操作系統的情況下,而這裏並沒有操作系統。
2.8086存在的缺點:
- 沒有操作系統的存在,直接訪問的是物理內存;
- 對內存沒有進行權限控制,可以任意的對某一塊內存進行修改;
- 沒有對ip進行安全檢查,如果ip特別大,產生越界訪問等不好的後果。
直接對物理內存進行操作,沒有操作系統保護,此狀態被叫做實模式,也叫實地址模式。
3.linux內核image加載:
- CPU剛通電,操作系統還沒有運行起來,CPU強制進入實模式,也就是8086運行的模式,也就是此時的CPU最多可以訪問1M的內存;
- 這也就是說爲什麼內核從1M以後開始加載,0x100000,1M內存放的式bois的緩存,顯卡的緩存,驅動代碼等內容。因爲1M前放的內容式必須要先訪問或者執行的。
三、80386的地址映射:保護模式
1.80386的新突破:
從8086得出一些經驗,8086是極其不安全不可靠的,原因如下:
- 沒有內存段的大小說明;
- 沒有內存訪問權限的控制;
- 內存的起始地址也可能被修改。
所以,後來,80386改善和解決8086存在的弊端,新增兩個32位寄存器:
- GDTR:全局段描述符表,保存全局段描述符表GDT的地址,常駐內存,進程共享
- LDTR:局部段描述符表,進程獨享,新版本中淘汰
GDT中的內容:GDT就是一個數組,保存內存段的信息
GDT數組的索引存放在哪裏:
從80386開始,CS DS SS ES用來存放段描述表的索引
此時這四個段寄存器的16位的含義不再是保存段起始地址,而是用來描述GDT數組的信息,如下
- 權限:00代表最高權限,也就是內核態,11代表最低權限,也就是用戶態;
- 8192:2^13 = 8k;也就是有這麼多的索引,即GDT[2^32-1],實際上,linux內核也會佔用一部分,大概是12個左右被內核保留使用,實際上用戶可以使用的是8180個。
GDT數組的某一項的含義: GDT[n],每一項元素大小爲8字節,64位
- B:base addr 起始地址,總共32位
- L:length 段內存長度,總共16位,2^16 = 1M,單位G表示
- G:表示段內存長度的單位:0表示以字節位單位,1表示段內存長度單位是頁面
- D、A、P、DPL、S:權限控制
2.保護模式下內存分段的地址映射:
GDT[DS>>3].baseaddr + IP(邏輯地址,需要和length比較一下,防止越界) = 線性地址
當基地址GDT[DS>>3].baseaddr ==0時,IP == 邏輯地址 == 線性地址
DS>>3:獲取高13位,也就是GDT數組的索引
GDT[DS>>3]:GDT數組的某一項
- 獲取到線性地址以後,檢查是否開啓分頁機制,如果沒有開啓,即線性地址 == 物理地址;
- 開啓了分頁機制,此時線性地址 == 虛擬地址,要進行分頁地址映射,才能得到物理地址。
3.補充提升:
- CR0:最高位,即PG位,0代表未開啓內存分頁,1代表開啓內存分頁
- CR2:發生缺頁異常的虛擬地址
- CR3:頁目錄的起始地址
- CR4:PAE位,物理地址擴展,0表示位開啓,1表示開啓
總線有外總線和內總線之分,我們程序中打印的地址是內總線發出的地址,也就是虛擬地址,即沒有經過頁表映射,沒有經過轉換的地址;
只有當虛擬地址經過了頁表映射等過程,纔會被放到外總線上,而外總線是直接連接內存的總線。