應(yīng)用程序處于特權(quán)級別3,操作系統(tǒng)內(nèi)核處于特權(quán)級0,當(dāng)用戶程序訪問系統(tǒng)資源時,(無論是硬件,還是內(nèi)核數(shù)據(jù)結(jié)構(gòu)),
它都需要進行系統(tǒng)調(diào)用,這樣CPU便進入了內(nèi)核態(tài),也稱為管態(tài)。
內(nèi)存訪問為什么要分段編譯器在編譯程序時,肯定要根據(jù)CPU訪問內(nèi)存的規(guī)則將代碼編譯成機器指令,這樣編譯出來的程序才能在該CPU上運行,
所以說,在直接以絕對物理地址訪問內(nèi)存的CPU上運行程序,該程序中指令地址也必須是絕對的物理地址。
總之要想在該硬件上運行,就要遵從該硬件的規(guī)則。
若加載程序運行,不管其是內(nèi)核程序,還是用戶程序,程序中的地址若都是絕對的物理地址,那該程序必須在內(nèi)存中的固定
地方,于是,兩個編譯的程序地址相同沒有辦法做到同時運行,只能運行一個,于是讓CPU采用了“段基址+段內(nèi)偏移地址”
的方式來訪問任意程序了,這樣的好處是程序可以重定位,盡管程序指令中給的是絕對的物理地址,但終究可以同時運行多個
程序了。
總結(jié):編譯器是根據(jù)CPU特性進行的指令機器碼生成,如果使用的都是絕對的物理地址那么就沒有辦法同時運行兩個編譯的程序,
因此給出了“段基址+段內(nèi)偏移”的方式實現(xiàn)了程序重定位進而為同時運行多個程序做好準備。
段基址+段內(nèi)偏移地址CPU設(shè)計者在地址處理單元中動了手腳,自動將段基址乘以16及左移4位,然后在和16位的段內(nèi)偏移相加,這下地址就變成了20位。
代碼中為什么存在代碼段,數(shù)據(jù)段?在X86平臺的處理器中必須用到分段訪問內(nèi)存,正因如此處理器才提供了段寄存器,用來指定待訪問內(nèi)存段起始地址,
在硬件的內(nèi)存訪問機制中,處理器要用硬件-段寄存器指向軟件中的內(nèi)存段。
平坦模式:硬件段寄存器中指向的內(nèi)存段大為4GB。
多段模式:硬件段寄存器中指向內(nèi)存段大小不一,像是匯編語言允許程序員自己分段,能夠靈活安排布局,屬于人為分段,
也就是采用了多段模型編程。
分頁模型:由于處理器支持具有分頁機制的虛擬內(nèi)存,操作系統(tǒng)也采用分頁模型因此編譯器將程序的內(nèi)容分為代碼段,
數(shù)據(jù)段,比如gcc編譯C語言程序就劃分了代碼段,數(shù)據(jù)段,棧段,.bss段,堆等內(nèi)容,操作系統(tǒng)會將編譯器編譯的
用戶程序段的內(nèi)容分配到不同的物理地址上。
段的不同屬性數(shù)據(jù)段本身是需要被修改的,所以數(shù)據(jù)段就需要要可寫屬性,程序中的代碼是不能被更改的,這樣就要去代碼段具備只讀屬性。
實現(xiàn)段不同的屬性:
1.編譯器負責(zé)挑選出數(shù)據(jù)具備的屬性,從而根據(jù)屬性將程序分段(代碼段/數(shù)據(jù)段)分類,比如劃分出只讀屬性的代碼段和寫屬性的數(shù)據(jù)段,
編譯器并沒有讓段具備某種屬性而是歸類到一起而已,也就是將程序多個section合并成一個大的segment。
2.操作系統(tǒng)通過設(shè)置GDT全局描述符表來構(gòu)造段描述符,在段描述符中指定段的位置,大小及屬性(包括S字段和TYPE字段),也就是說
操作系統(tǒng)認為代碼段是只讀的,所以給用來指向代碼段的那個段描述符設(shè)置了只讀屬性,這才是真正的段添加屬性的地方。
3.CPU中的段寄存器提前被操作系統(tǒng)賦予相應(yīng)的的選擇子,從而確定了指向的段,在執(zhí)行指令時,會根據(jù)該段的屬性來判斷指令的行為,
若有返回則發(fā)出異常。
總結(jié):編譯器/操作系統(tǒng)/CPU這個三個的配合在一起才能對程序保護。
物理地址,邏輯地址,有效地址,線性地址,虛擬地址的區(qū)別物理地址:在實模式下段基址+段偏移地址經(jīng)過段部件的處理,直接輸出的就是物理地址,CPU可以直接訪問。
線性地址:在保護模式下段基址+段偏移稱為線性地址,不過段基址并不是真正的地址了,而是被稱為段選擇子,本質(zhì)上是一個
索引,類似于數(shù)組下標,這個索引能在GDT(全局描述符表)中找到相應(yīng)的段描述符,該描述符記錄了段的起始地址,大小等信息,
這樣便獲得了段基址,沒有開啟分頁功能,線性地址就是物理地址可以直接訪問內(nèi)存。
虛擬地址:虛擬地址是保護模型下的一種模式,是在開啟分頁功能后將線性地址轉(zhuǎn)變?yōu)樘摂M地址而非是物理地址,虛擬地址需要經(jīng)過CPU的
頁部件轉(zhuǎn)換成具體物理地址。
有效地址:無論是保護模式還是實模式,段內(nèi)偏移地址又被稱為有效地址,也被稱為邏輯地址。
段重疊段重疊是指兩個段基址+偏移后得到的地址范圍相重合,比如C00+05和C02+2,C00和C02就重疊。
平坦模型平臺模式是相對于多端模式而言的,在實模式下訪問超過64KB的內(nèi)存需要重新指定不同的段,需要迂回的方式才能達成目標,
在保護模式下其是32位的,尋址能夠達到4GB,段內(nèi)偏移地址也是地址,所以32位環(huán)境下一個段就能夠訪問所有內(nèi)存了,所以稱為
平坦模式,相較于多段模式需要A20地址線延申訪問1MB空間,平坦模式則不需要。
cs,ds這類sreg寄存器,位寬是多少CS 代碼段寄存器(Code Segment Register),其值是代碼段的段基址。
DS 數(shù)據(jù)段寄存器(Data Segment Register),其是數(shù)據(jù)段的段基址。
ES 附加段寄存器(Extra Segment Register),其值是附加段的段基址,稱為附加是因為此段寄存器用途不想其他sreg固定。
FS 附加段寄存器(Extra Segment Register),其值是附加段的段基址,用途不固定。
GS 附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段基址,用途不固定。
SS 堆棧段寄存器(Stack Segment Register),其值為堆棧的段值。
每種模式下段寄存器的意義不同:
實模式:CS/DS/ES/SS的值為段基址,是具體的物理地址,內(nèi)存單元的邏輯仍然是段基址+段內(nèi)偏移
保護模式:段寄存器不在是段地址,而是段選擇子(Selector),選擇子也是數(shù)值,長度仍然是16位。
結(jié)論:32位的CPU,sreg無論是工作在16位的實模式中,還是32位保護模式中用的段寄存器都是同一組,
32位下的段選擇子是16位寬度,排除了寄存器32位環(huán)境下是32位寬的可能,sreg都是16位寬。
編譯器程序和解析型程序的區(qū)別解析型語言:JavaScript/Python/Perl/PHP/等,它們本身是文本文件,是某個應(yīng)用程序的輸入這個應(yīng)用程序就是腳本解析器,
腳本中的代碼沒有真正上過CPU去執(zhí)行,cs:ip從來沒指向過它們,CPU眼里只有腳本解析器,本質(zhì)上腳本解析器實時分析腳本運行。
編寫型語言:運行時本身就是一個進程,由操作系統(tǒng)直接調(diào)用將CS:IP直接指向這個程序入口,使它在CPU上運行。
大端字節(jié)序/小端字節(jié)序內(nèi)存是以字節(jié)為單位進行讀寫的,其最小的讀寫單位就是字節(jié)。
小端字節(jié)序:
數(shù)值的低位放在內(nèi)存的低位,數(shù)據(jù)的高字節(jié)放在內(nèi)存的高字節(jié)。
大端字節(jié)序:
數(shù)值的低位放在內(nèi)存的高位,數(shù)據(jù)高位放在內(nèi)存的低位。
兩種字節(jié)序的優(yōu)勢
小端:
因為低位在低字節(jié),強制數(shù)據(jù)轉(zhuǎn)換數(shù)據(jù)型時不需要再調(diào)整字節(jié)了。
大端:
有符號數(shù),其字節(jié)最高位不僅表示數(shù)據(jù)本身,還起到了符號的作用,符號位固定為第一個字節(jié),
也就是最高位占據(jù)最低地址,符號直接可以取出來,容易判斷正負。
最高位在最低地址,也就是說可以直接取到,不用在跨越幾個字節(jié),減少了時鐘周期。
強制數(shù)據(jù)轉(zhuǎn)換方式:
在強制數(shù)據(jù)轉(zhuǎn)換時,如果轉(zhuǎn)換是由低精度轉(zhuǎn)向高精度,這數(shù)值本身是沒有變化的,如short是2字節(jié),將其
轉(zhuǎn)換為4字節(jié)的int類型,無非是0x1234變成0x00001234,數(shù)值上是不變的,只是存儲形式發(fā)生了變化,
如果高精度轉(zhuǎn)向低精度,這必然要丟失一些字節(jié),編譯器的轉(zhuǎn)換原則是強制轉(zhuǎn)換低精度類型,丟棄數(shù)值的高字節(jié),
只保留低字節(jié),比如:0x12345678強制轉(zhuǎn)換后0x5678。
總結(jié):
低精度轉(zhuǎn)高精度數(shù)值不變。
高精度轉(zhuǎn)低精度丟棄高字節(jié)保留低字節(jié)。
常見CPU字節(jié)序大端字節(jié)序:IBM Sun PowerPC
小端字節(jié)序:x86 DEC
ARM體系則大小端字節(jié)序通吃,具體用那類字節(jié)序由硬件決定。
字節(jié)序不僅是CPU中內(nèi)存的概念,也存在于文件存儲和網(wǎng)絡(luò)傳輸中,bmp格式文件是小端字節(jié)序,jpg則是大端字節(jié)序,
這些完全是按照設(shè)計者設(shè)計的。
網(wǎng)絡(luò)字節(jié)序:網(wǎng)絡(luò)字節(jié)序就是大端字節(jié)序。
BIOS中斷/DOS中斷/Linux中斷的區(qū)別事件:
無論是保護模式還是實模式,在任何情況下都會有來自內(nèi)部或者外部的事件發(fā)生,
如果事件來自于CPU內(nèi)部就被稱為異常(Exception),比如CPU在計算時發(fā)現(xiàn)分母為0,就會拋出0異常。
如果事件源于外部,也就是該事件由外部設(shè)備觸發(fā)并通知CPU,這個事件就被稱為中斷。
中斷向量表(Interrupt Vector Table IVT):
BIOS和DOS都存在于實模式下的程序,它們建立的中斷調(diào)用就是建立在中斷向量表中的,它們通過軟中斷
int中斷號調(diào)用的。
中斷向量表中的中斷向量大小為4個字節(jié),這個4個字節(jié)描述了中斷處理例程(程序)的段基址和段內(nèi)偏移地址,
因為中斷向量表長度1024字節(jié),最多只能容納256個中斷向量處理程序。
計算機的啟動之初中斷向量表的中斷例程是由BIOS建立的,它從物理內(nèi)存的0x0000處初始化,并在中斷向量表中添加
各種處理例程。
BIOS為什么需要中斷向量表:
BIOS的中斷向量表的主要功能是提供了硬件訪問的方法,該方法是的對硬件的操作變得簡單易行。
BIOS是通過in/out指令來操作硬件寫外設(shè)端口,BIOS中斷向量表是處理硬件的。
BIOS為什么添加中斷向量表例程:
1.給直接用避免重復(fù)性的某些代碼,直接寫成中斷函數(shù)。
2.給后來的程序用,如加載器boot loader,它們在調(diào)用硬件資源時就不需要自己寫重復(fù)代碼。
BIOS如何填寫中斷向量表例程:
BIOS在運行期間會掃描0xC0000到0xE0000之間的內(nèi)存,若是在某個區(qū)域發(fā)現(xiàn)前兩個字節(jié)都是
0x55,0xAA時,意味著這片區(qū)域存在ROM代碼的存在,在做該區(qū)域的累加和檢查若結(jié)果與第3個字節(jié)
的值相符,說明代碼無誤,從第4個字節(jié)進入,這個時候就開始執(zhí)行硬件的自帶的例程以及初始化硬件,
最后BIOS填寫中斷向量表相關(guān)項。
BIOS中斷:
中斷向量表中的0H~1FH項是BIOS中斷。
硬件操作每個外設(shè)包括如顯卡/硬盤等都有自己的內(nèi)存,但是這種內(nèi)存是只讀存儲器ROM,硬件的自己功能調(diào)用例程以及
初始化代碼就存放在ROM中,根據(jù)規(guī)范第一個內(nèi)存單元是0x55,第二個存儲單元是0xAA,第三個存儲單元應(yīng)該就是rom中以
512字節(jié)為單位的代碼長度,第四個存儲單元就是實際代碼了,直到第三個存儲單元所示的長度為止。
CPU訪問外設(shè)ROM的方式:
1.內(nèi)存映射:
通過地址總線的方式將外設(shè)自己的內(nèi)存映射到某個內(nèi)存區(qū)域,并不是映射到主板上插的內(nèi)存條中。
物理內(nèi)存中0xA0000開始到0xFFFFF這部分內(nèi)存中一部分是專門用來做映射的,如果硬件存在,
硬件自己的ROM會被映射到這片內(nèi)存中的某處。
2.端口操作:
外設(shè)都有自己的控制器,控制器上有寄存器,這些就寄存器就是所謂的端口,通過in/out指令讀寫端口來訪問硬件的內(nèi)存。
DOS中斷調(diào)用與BIOS中斷調(diào)用與Linux中斷DOS運行在實模式下,建立的中斷調(diào)用也是在中斷向量表中,不過中斷向量號不能跟BIOS的沖突。
0x20~0x27是DOS中斷,因為DOS在實模式下運行因此可以調(diào)用BIOS中斷。
DOS中斷只占用0x21中斷號,也就是DOS只有一個中斷例程。
DOS中斷調(diào)用實現(xiàn):
先向ah寄存器寫好子功能號,再執(zhí)行int 0x21,這時中斷向量表中0x21表項即物理地址的0x21*4處的中斷處理程序開始
根據(jù)寄存器ah中的值來調(diào)用相應(yīng)的子功能。
DOS中斷總結(jié):
1.DOS中斷例程跟BIOS中斷一樣都存在于中斷向量表IVT中
2.0x20~0x27是DOS中斷
3.DOS中斷只占用了0x21中斷號,DOS只有一個中斷例程
4.寄存器ah值子功能號,執(zhí)行int 0x21來調(diào)用相應(yīng)的子功能
Linux中斷:
Linux是在進入內(nèi)核之后才建立的中斷例程,在保護模式下中斷向量表已經(jīng)不存在了,取而代之的是中斷描述符(Interrupt Descriptor Table,IDT),
在Linux下執(zhí)行的中斷例程是在中斷描述符表中,已經(jīng)不在中斷向量表中了。
Linux中斷與DOS中斷類似,Linux是通過int 0x80指令進入一個中斷程序后再根據(jù)eax寄存器的值來調(diào)用不同的子功能函數(shù),如果在實模式下執(zhí)行
int指令會自動訪問中斷向量表,如果在保護模式下運行執(zhí)行int指令則會自動訪問中斷描述符。
Linux中斷總結(jié):
1.Linux中斷與DOS中斷類似
2.Linux中斷例程是在中斷描述符中而非中斷向量表
3.Linux是通過int 0x80根據(jù)eax中的值來調(diào)用子功能函數(shù)
4.在保護模式下int處理的是中斷描述符IDT,實模式下是中斷向量表IVT
Section和Segment的區(qū)別在匯編語言中語法關(guān)鍵字section或segment來表示一段區(qū)域,操作系統(tǒng)加載程序時并不關(guān)心節(jié)的數(shù)量和大小,
操作系統(tǒng)只關(guān)心節(jié)的屬性,因為程序必然需要加載到內(nèi)存中才能夠運行,而內(nèi)存的訪問會涉及全局描述符表,
中斷描述符的訪問權(quán)限等屬性,保護模式下任何任何對內(nèi)存的操作都必須經(jīng)過段描述符表。
section成為節(jié)是匯編語言中關(guān)鍵字section和segment修飾,邏輯劃分的指令或數(shù)據(jù)區(qū)域匯編器會將這兩個關(guān)鍵字
修飾的區(qū)域在目標文件編譯成節(jié),節(jié)最初誕生于目標文件中。
segment成為段,是鏈接器根據(jù)目標文件中屬性相同的多個section合并后的section集合,這個集合被成為segment,也就是段。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
當(dāng)前名稱:操作系統(tǒng)真相還原第0章筆記-創(chuàng)新互聯(lián)
本文地址:http://www.rwnh.cn/article4/jogoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、響應(yīng)式網(wǎng)站、用戶體驗、自適應(yīng)網(wǎng)站、網(wǎng)站內(nèi)鏈、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容