• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            luqingfei@C++

            為中華之崛起而崛起!
            兼聽則明,偏聽則暗。

            Win32匯編--需要了解的基礎知識

            在一個月前我打算學Win32匯編,發現匯編的基礎不是太好,便花了近一個月的時間把王爽老師的《匯編語言》看了一遍。現在再來看Win32匯編,比一個月前輕松了不少。真是本看書,對于我個人來說。

            接下來,我將繼續Win32匯編的學習。堅持、堅持!

            Let's go!

             

            Background

             

            Windows環境下32位匯編語言是一種全新的編程語言。它使用與C++語言相同的API接口,不僅可以用來開發出大型的軟件,而且是了解操作系統運行細節的最佳方式。

             

            Win32指的是32位的Windows系列操作系統。

             

            19905月份微軟推出了Windows 3.0,可以支持Intel 80286/386/486微處理器的保護模式,并可以訪問達16MB的內存。Windows 3.0一面世便在商業上取得了驚人的成功,從而一舉奠定了Microsoft在操作系統上的壟斷地位。

             

            19924月,Microsoft推出了更穩定的Windows 3.1,可以支持True Type字體。Windows 3.116Windows中最流行的版本。

             

            19935月,Microsoft發布了具備安全性和穩定性特征的32位操作系統Windows NT 3.11,主要針對網絡和服務器市場。NT代表新技術(New Technology)。NT 3.11Windows系列中使用32位編程模式的第一個版本。它充分利用80386及以上處理器的平面地址空間和保護模式等新技術。

             

            19958月,Microsoft推出新一代操作系統Windows 95Windows 95實現了很友好的用戶界面,支持即插即用功能,支持主流多媒體設備和DirectX編程接口,成為Microsoft發展史上的一個里程碑,也是操作系統發展史上的一個里程碑。從此,Windows 9x便取代了Windows 3.xMS-DOS操作系統,成為個人計算機平臺的主流操作系統。

             

            1998Microsoft又發布了使用更方便的Windows 98

             

            在操作系統的分類上,Microsoft根據家庭個人用戶和商業辦公用戶的不同需求,分別提供Windows 9xWindows NT系列,Windows 9x注重用戶界面及其他易用性特征,而NT系列則在純32位內核的穩定性和可靠性等企業級特征上下功夫。

             

            2000年,微軟發布采用純32位內核并照顧了家庭消費類應用軟件的Windows NT 5.0,即Windows 2000。至此Micosoft的兩個系列操作系統(9xNT)終于開始統一。

             

            為了利用MS-DOS時代大量的應用程序,保持向下的兼容性,Windows 9x的內核模塊還有許多地址使用16位程序,但在編程上,支持32位的編程模式。

             

            Windows NT系列和Windows 9x系列操作系統都支持Win32 APIApplication Programming Interface),即Windows 32位應用程序編程接口,Win32 API為應用程序提供了大量的系統功能調用,通過Win32 API調用Windows系統相當于在MS-DOS中通過中斷方式調用系統功能。就像DOS匯編程序中隨處可見的 INT 21h指令一樣,Windows應用程序中Win32 API也隨處可見。

             

            Windows的特色

            對于使用者來說:

            1)圖形用戶界面;(GUIGraphic User Interface Windows最重要的特色。

            2)一致的用戶界面; 便于使用。

            3)多任務。 非常重要的特色。用戶可以同時運行多個程序,可以在不同的程序之間傳送數據。

             

            對于程序員來說,更關心隱藏在底下的東西:

            1大量的函數調用Win32支持上千種函數的調用,幾乎涉及所有的方面,程序員可以把更多的時間放在程序的邏輯結構和用戶界面上。

            2和設備的無關性Win32程序并不直接訪問屏幕、打印機和鍵盤等硬件設備,Windows虛擬了所有的硬件。只要有硬件的設備驅動程序,這個硬件就可以使用,應用程序并不需要關心硬件的具體型號。與DOS編程中需要針對不同的顯示卡和打印機等編寫很多的驅動程序來比,這個特性對程序員的幫助是巨大的。

            3內存管理。由于內存分頁和虛擬內存的使用,每個程序都可以使用4GB的地址空間,DOS編程時必須考慮的640KB的內存問題已經成為歷史。

             

             

            必須了解的東西

             

            80x86處理器的工作模式

             

            80386處理器有3種工作模式:實模式、保護模式和虛擬86模式。

            實模式和虛擬86模式是為了和8086處理器兼容而設置的。在實模式下,80386處理器就相當于一個快速的8086處理器。

            保護模式是80386處理器的主要工作模式。在此方式下,80386可以尋址4GB的地址空間,同時,保護模式提供了80386先進的多任務、內存分頁管理和優先級保護等機制。

             

            為了在保護模式下繼續提供和8086處理器的兼容,80386又設計了一種虛擬86模式,以便可以在保護模式的多任務條件下,有的任務運行32位程序,有的任務運行MS-DOS程序。

            在虛擬86模式下,同樣支持任務切換、內存分頁管理和優先級,但內存的尋地址方式和8086相同,也是可以尋址1MB的空間。

             

             

            實模式是80386處理器工作的基礎,這時80386當做一個快速的8086處理器工作。在實模式下可以通過指令切換到保護模式,也可以從保護模式退回實模式。

            虛擬86模式則以保護模式為基礎,在保護模式和虛擬86模式之間可以互相切換,但不能從實模式直接進入虛擬86模式或從虛擬86模式直接退到實模式。

             

             

            實模式

            80386處理器被復位或加電的時候以實模式啟動。這時候處理器中的各寄存器以實模式的初始化值工作。80386處理器在實模式下的存儲器尋址方式和8086是一樣的,由段寄存器的內容乘以16當做基地址,加上段內的偏移地址形成最終的物理地址,這時候它的32位地址線只使用了低20位。在實模式下,80386處理器不能對內存進行分頁管理,所以指令尋址的地址就是內存中實際的物理地址。在實模式下,所有的段都是可以讀、寫和執行的。

             

            實模式下80386不支持優先級,所有的指令相當于在工作在特權級(優先級0),所以它可以執行所有特權指令,包括讀寫控制寄存器CR0等。實際上,80386就是通過在實模式下初始化控制寄存器,GDTRLDTRIDTRTR等管理寄存器以及頁表,然后再通過加載CR0使其中的保護模式使能位置位而進入保護模式的。實模式下不支持硬件上的多任務切換。

             

            實模式下的中斷處理方式和8086處理器相同,也用中斷向量表來定位中斷服務程序地址。中斷向量表的結構也和8086處理器一樣,每4個字節組成一個中斷向量,其中包括兩個字節的段地址和兩個字節的偏移地址。

             

            從編程的角度看,除了可以訪問80386新增的一些寄存器外,實模式的80386處理器相比8086,其最大的好處是可以使用8038632位寄存器,用32位寄存器進行編程可以使計算程序更加簡捷,加快了執行速度。其次,80386中增加的兩個輔助段寄存器FSGS在實模式下也可以使用,這樣,同時可以訪問的段達到了6個而不必考慮重新裝入的問題;最后,很多80386的新增指令也使一些原來不很方便的操作得以簡化,如80386中可以使用下述指令進行數組訪問:

                   mov cx,[eax + ebx * 2 + 數組基地址]

                   這相當于把數組下標為eaxebx的項目放入cx中;ebx*2中的2可以是1,2,48,這樣就可以支持8位到64位的數組。

            另外,pushadpopad指令可以一次把所有8個通用寄存器的值壓入或從堆棧中彈出,比起用下面的指令分別將8個寄存器入棧要快了很多:

                   push eax

                   push ebx

                  

                   pop ebx

                   pop eax

             

            當然,使用了這些新指令的程序是無法拿回到8086處理器上去執行的,因為這些指令的編碼在8086處理器上是未定義的。

             

             

            保護模式

            80386工作在保護模式下的時候,它的所有功能都是可用的。這時80386所有的32根地址線都可供尋址,物理尋地址空間高達4GB。在保護模式下,支持內存分頁機制,提供了對虛擬內存的良好支持。雖然與8086可尋址的1MB物理地址空間相比,80386可尋地址的物理地址空間可謂很大,但實際的微機系統不可能安裝如此大的物理內存。所以,為了運行大型程序和真正實現多任務,虛擬內存是一種必需的技術。

             

            保護模式下80386支持多任務,可以依靠硬件僅在一條指令中實現任務切換。任務環境的保護工作是由處理器自動完成的。在保護模式下,80386處理器還支持優先級機制,不同的程序可以運行在不同的優先級上。優先級一共分0~3 四個級別,操作系統運行在最高的優先級0上,應用程序則運行在比較低的級別上;配合良好的檢查機制后,既可以在任務間實現數據的安全共享也可以很好地隔離各個任務。從實模式切換到保護模式是通過修改控制寄存器CR0的控制位PE(位0)來實現的。在這之前還需要建立保護模式必需的一些數據表,如全局描述符表GDT和中斷描述符表IDT等。

             

            DOS操作系統運行于實模式下,而Windows操作系統運行于保護模式下。

             

             

            虛擬86模式

            虛擬86模式是為了在保護模式下執行8086程序而設置的。雖然80386處理器已經提供了實模式來兼容8086程序,但這時8086程序實際上只是運行得快了一點,對CPU的資源還是獨占的。在保護模式的多任務環境下運行這些程序時,它們中的很多指令和保護模式環境格格不入,如段尋址方式、對中斷的處理和I/O操作的特權問題等。為了在保護模式下工作而丟棄這些程序的代價是巨大的。設想一下,如果Windows80386處理器推出的時候宣布不能運行以前的MS-DOS程序,那么就等于放棄了一個巨大的軟件庫,Windows以及80386處理器可能就會落得和蘋果機一樣的下場,這是MicrosoftIntel都不愿意看到的。所以,80386處理器又設計了一個虛擬86模式。

             

            虛擬86模式是以任務形式在保護模式上執行的,在80386上可以同時支持由多個真正的80386任務和虛擬86模式構成的任務。在虛擬86模式下,80386支持任務切換和內存分頁。在Windows操作系統中,有一部分程序專門用來管理虛擬86模式的任務,稱為虛擬86管理程序。

             

            既然虛擬86模式以保護模式為基礎,它的工作方式實際上是實模式和保護模式的混合。為了和8086程序的尋地址方式兼容,虛擬86模式采用和8086一樣的尋址方式,即用段寄存器乘以16當作基址再配合偏移地址形成線性地址,尋址空間為1MB。但顯然多個虛擬86任務不能同時使用同一位置的1MB地址空間,否則會引起沖突。操作系統利用分頁機制將不同虛擬86任務的地址空間映射到不同的物理地址上去,這樣每個虛擬86任務看起來都認為自己在使用0~1MB的地址空間。

             

            8086代碼中有相當一部分指令在保護模式下屬于特權指令,如屏幕中斷的cli和中斷返回指令iret等。這些指令在8086程序中是合法的。如果不讓這些指令執行,8086代碼就無法工作。為了解決這個問題,虛擬86管理程序采用模擬的方法完成這些指令。這些特權指令執行的時候引起了保護異常。虛擬86管理程序在異常處理程序中檢查產生異常的指令,如果是中斷指令,則從虛擬86任務的中斷向量表中取出中斷處理程序的入口地址,并將控制轉移過去;如果是危及操作系統的指令,如cli等,則簡單地忽略這些指令,在異常處理程序返回的時候直接返回到下一條指令。通過這些措施,8086程序既可以正常地運行下去,在執行這些指令的時候又覺察不到已經被虛擬86管理程序做了手腳。MS-DOS應用程序在Windows操作系統中就是這樣工作的。

             

             

            Windows的內存管理

            Win32匯編中,每個程序都可以用4GB的內存嗎?

            Win32匯編源代碼中為什么看不到CSDSESSS等段寄存器的使用?

             

            DOS操作系統的內存安排

            Win32編程相對于DOS編程最大的區別之一就是內存的使用。

            00000h

            中斷向量表

            00400h

            BIOS數據區

            00500h

            DOS數據區

             

            系統程序

            DOS的駐留部分、驅動程序等)

             

            可用空間

            A0000h

            圖形模式視頻緩沖區

            B0000h

            單色字符模式視頻緩沖區

            B8000h

            彩色字符模式視頻緩沖區

            C0000h

            VGA BIOS地址

            C8000h

            ROM擴展、系統BIOS地址

            FFFFFh

            64KB高端內存

             

             

            在實模式下,一個內存尋址方式是,一個完整的地址由段地址和偏移地址兩部分組成。段地址放在16位的段寄存器中,然后在指令中用16位的偏移地址尋址。處理器換算時先將段地址乘以10h(即16),得到段在物理內存中的起始地址;然后 加上16位的偏移地址得到實際的物理地址。

             

            80386處理器工作在保護模式和虛擬8086模式的時候,可以使用全部32根地址線訪問內存4GB大的內存。段地址加偏移地址的計算方法顯然無法覆蓋這么大的范圍。但計算一下就可以發現,實際上和8086同樣的限制已經不復存在,因為80386所有的通用寄存器都是32位的,232次方相當于4G,所以用任何一個通用寄存器來間接尋址,不必分段就已經可以訪問到所有的內存地址。

             

            這是不是說,在保護模式下,段寄存器就不再有用了呢?答案是否定的。實際上段寄存器更有用了,雖然在尋址上不再有分段的限制問題,但在保護模式下,一個地址空間是否可以被寫入,可以被多少優先級的代碼寫入,是不是允許執行等涉及保護的問題就出來了。要解決這些問題,必須對一個地址空間定義一些安全上的屬性。段寄存器這時就派上了用途。但是涉及屬性和保護模式下段的其他參數,要表示的信息太多了,要用64位長的數據才能表示。我們把這64位的屬性數據叫做段描述符(Segment Desciptor)。

             

            80386的段寄存是16位的,無法放下保護模式下64位的段描述符。解決辦法是把所有段的段描述符順序放在內存中的指定位置,組成一個段描述符表(Descriptor Table);而段寄存器中的16位用來做索引信息,指定這個段的屬性用段描述符表中的第幾個描述符來表示。這時,段寄存器中的信息不再是段地址了,而是段選擇器(Segment Selector)。可以通過它在段描述符表中,選擇一個項目以得到段的全部信息。

             

            既然這樣,段描述符表放在哪里呢?80386中引入了兩個新的寄存器來管理段描述符表。一個是48位的全局描述符表寄存器GDTRGlobal Descriptor Table Register),一個是16位的局部描述符表寄存器LDTRLocal Descriptor Table Register)。那么,為什么有兩個描述符表寄存器呢?

             

            GDTR指向的描述符表為全局描述符表GDTGlobal Descriptor Table)。它包含系統中所有任務都可用的段描述符,通常包含描述操作系統所使用的代碼段、數據段和堆棧段的描述符及各任務的LDT段等;全局描述符表只有一個。

             

            LDTR則指向局部描述符表LDTLocal Descriptor Table)。80386處理器設計成每個任務都有一個獨立的LDT。它包含有每個任務私有的代碼段、數據段和堆棧段的描述符,也包含該任務所使用的一些門描述符,如任務門和調用門描述符等。

             

            不同任務的局部描述符表分別組成不同的內存段,描述這些內存段的描述符當做系統描述符放在全局描述符表中。和GDTR直接指向內存地址不同,LDTRCSDS等段選擇器一樣只存放索引值,指向局部描述符表內存段對應的描述符在全局描述符表中的位置。隨著任務的切換,只要改變LDTR的值,系統當前的局部描述符表LDT也隨之切換,這樣便于各任務之間數據的隔離。但GDT并不隨著任務的切換而切換。

             

            看到這里,讀者可能會提出一個問題,既然有全局描述符表和局部描述符表兩個表,那么段選擇器中的索引值對應哪個表中的描述符呢?實際上,16位的段選擇器中只有高13位表示索引值。剩下的3個數據位中,第01位表示程序的當前優先RPL;第2TI位用來表示在段描述符的位置;TI=0表示在GDT中,TI=1表示在LDT中。

             

             

            80386的內存分頁機制

            在實模式下尋址的時候,段寄存器+偏移地址經過轉換計算以后得到的地址是物理地址,也就是在物理內存中的實際地址。

            而保護模式下,段選擇器+偏移地址轉換后的地址被稱為線性地址,而不是物理地址。

             

            線性地址是物理地址嗎?

            可能是,也可能不是,這取決于80386的內存分頁機制是否被使用。

            在單任務的DOS系統中,一個應用程序可以使用所有的空閑內存。程序退出后,操作系統回收所有的碎片內存并且合并成一個大塊內存繼續供下一個程序使用。內存合并過程中的一個極端情況匯報系統中有多個TSR卸載后,后裝入的TSR會留存內存的中間部位,把空閑內存隔成兩個區域。這時應用程序使用的最大內存塊只能是這兩塊內存中較大的一塊,無法將它們合并使用。

             

            對于一個多任務的操作系統,內存的碎片化是不能容忍的。否則,經過一段時間后,即使空閑內存的總和很大,也可能出現任何一處內存都小到無法裝入執行程序的地步。所以多任務操作系統中碎片內存的合并是個很重要的問題。

             

            80386處理器的分頁機制可以很好地解決這個問題。80386處理器把4KB大小的一塊內存當做一頁內存,每頁物理內存可以根據頁目錄和頁表,隨意映射到不同的線性地址上。這樣,就可以將物理地址不連續的內存的映射連到一起,在線性地址上視為連續。在80386處理器中,除了和CR3寄存器(指定當前頁目錄的地址)相關的指令使用的是物理地址外,其他所有指令都是用線性地址尋址的。

             

            是否啟用內存分頁機制是由80386處理器新增的CR0寄存器中的位31PG位)決定的。如果PG=0,則分頁機制不啟用,這時所有指令尋址的地址(線性地址)就是系統中實際的物理地址;當PG=1的時候,80386處理器進入內存分頁管理模式,所有的線性地址要經過頁表的映射才得到最后的物理地址。

             

            內存分頁管理只能在保護模式下才可以實現,實模式不支持分頁機制。但不管在哪種模式下,所有尋址指令使用的都是線性地址,程序不用關心數據最后究竟存放在物理內存的哪個地方。

             

            頁表規定的不僅是地址的映射,同時還規定了頁的訪問屬性,如是否可寫、可讀和可執行等。比如把代碼所在的內存頁設置為可讀與可執行,那么權限不夠的代碼向它寫數據就會引發保護異常。利用這個機制可以在硬件層次上支持虛擬內存的實現。

             

            頁表可以指定一個頁面并不真正映射到物理內存中,這樣,訪問這個頁的指令會引發頁異常錯誤。這時,處理器會自動轉移到頁異常處理程序中去,操作系統可以在異常處理程序中將硬盤上的虛擬內存讀到內存中并修改頁表重新映射,然后重新執行引發異常的指令。這樣指令可以正常執行下去。

             

             

            Windows的內存安排

            Windows系統一般在硬盤上建立大小為物理內存兩倍左右的交換文件(文件名在Windows 9x下為Win386.swpWindows NT下為PageFile.sys)用做虛擬內存。

            利用80386處理器的內存分頁機制,交換文件在尋地址上可以很方便地作為物理內存使用。只需在真正訪問到的時候將硬盤文件的內容讀入物理內存,然后重新將線性地址映射到這塊物理內存就可以了。同樣道理,被執行的可執行文件也不必真正裝入內存,只要在頁表中建立映射關系,以后到真正訪問到的時候再調入物理內存。

             

            如果把虛擬內存暫時先視為物理內存的一部分,從物理內存中的層次看,Windows操作系統和DOS一樣,也是所有的內容共享內存,如操作系統使用的代碼和數據(GDTLDT與頁表等),當前執行中的所有程序的代碼和數據以及這些程序調用的DLL的代碼和數據等。

             

            但是從應用程序代碼的層次看,也就是說從分頁映射后線性地址層次看,內存的安排卻不是這個樣子。因為Windows是一個分時的多任務操作系統,CPU時間被分成一個個的時間片后分配給不同程序輪流使用,在一個程序的時間片中,和這個程序執行無關的東西(如其他程序的代碼和數據)并不需要映射到線地址中去。

             

            Windows操作系統通過切換不同的頁表內容讓線性地址在不同的時間片中映射不同的內容。在物理內存中,操作系統和系統DLL的代碼需要供每個應用程序調用,所以在所有的時間片中都必須被映射;用戶程序只在自己所屬的時間片內被映射;而用戶DLL則有選擇地被映射。

             

             

            Win32編程中幾個很重要的概念:

            每個應用程序都有自己的4GB的尋址空間。該空間可存放操作系統、系統DLL和用戶DLL的代碼,它們之中有各種函數供應用程序調用。再除去其他的一些空間,余下的是應用程序的代碼、數據和可以分配的地址空間。

             

            不同應用程序的線性地址空間是隔離的。雖然它們在物理內存中同時存在,但在某個程序所屬的時間片中,其他應用程序程序的代碼和數據沒有被映射到可尋地址的線性地址中,所以是不可訪問的。從編程的角度看,程序可以使用4GB的尋址空間,而這個空間是私有的。

             

            DLL程序沒有自己的私有的空間。它們總是被映射到其他應用程序的地址空間中,當做和其他應用程序的一部分運行。原因很簡單,如果它不和其他程序同屬一個地址空間,應用程序該如何調用它呢?

             

            Win32匯編的角度看內存尋址

            DOS下的分段尋地址方式令人一頭霧水,80386保護模式的內存管理就更復雜。

             

            Windows是一個多任務操作系統,最首要的宗旨就是穩定壓倒一切,如果描述符表以及頁表等內容交給用戶程序是很不安全的,不用說全局描述符表,就是為每個程序建立的局部描述符表也不應該讓用戶程序改寫,否則用戶可以通過構造自己的描述符來訪問操作系統不希望用戶訪問的東西。任何權限上開放引發的安全問題都是很嚴重的。

            病毒程序就是利用這些系統漏洞,提升自身的權限,做一些破壞動作的。

             

            所以,Windows操作系統干脆為用戶程序安排好了一切。具體表現在為用戶程序的代碼段、數據段和堆棧段全部預定義好了段描述符。這些段的起始地址為0,限長為ffffffff,所以用它們可以直接尋址全部的4GB地址空間。程序開始執行的時候,CSDSESSS都已經指向了正確的描述符,在整個程序的生命周期內,程序員不必改動這些段寄存器,也不必關心它們的值究竟是多少(實際上,想改也改不了)。

             

            所以對Win32匯編程序來說,整個源程序中竟然可以不用出現段寄存器的身影。這在DOS匯編編程中是不可想象的。

             

            并不是Win32匯編源代碼用不到段寄存器,而是用戶在使用中不必去關心段寄存器。

             

             

            Windows的特權保護

            Windows的特權保護和處理器硬件的支持是分不開的。

            優先級的劃分、指令的權限檢查和超出權限訪問的異常處理等是構成特權保護的基礎。

            1Win32匯編中為什么找不到中斷指令的使用?

            2Windows錯誤的藍屏屏幕是從哪里來的?

             

            80386的中斷和異常

            中斷指當程序執行過程中有更重要的事情需要實時處理時(如串口中有數據到達,不及時處理數據會丟失,串行控制器就提交一個中斷信號給處理器要求處理),硬件通過中斷控制器通知處理器。處理器暫時掛起當前運行的程序,轉移到中斷處理程序中;當中斷處理程序處理完畢后,通過iret指令回到原先被打斷的程序中繼續執行。

             

            異常指指令執行中發生不可忽略的錯誤時(如遇到無效的指令編碼,除法指令除零等),處理器用和中斷處理相同的操作方法掛起當前運行的程序轉移到異常處理程序中。異常處理程序決定在修正錯誤后是否回到原來的地方繼續執行。

             

            更為DOS匯編程序員熟悉的中斷,指的是用int n指令直接轉移到中斷向量n指定的中斷處理程序中執行。嚴格地講,int n指令應該算自陷而不是中斷。因為這時并不是程序被急需解決的事情打斷。而是自己要求停止執行并轉移到中斷處理程序中去。

             

            不管中斷、異常還是自陷,雖然它們產生的原因不同,但處理過程是類似的,都通過中斷向量表里存放的入口地址轉移到服務程序,都由CPU自動在堆棧中保護斷點地址,最后也都可以用iret指令返回指令被中斷的地方。

             

            808680386實模式下中斷和異常的處理過程。

            中斷和異常服務程序地址存放在中斷向量表中。中斷向量表位于物理內存00000h開始的400h字節中,共支持100h個中斷向量;每個中斷向量是一個xxxx:yyyy格式的地址,占用4字節。當發生n號異常或n號中斷,或者執行到int n指令的時候,CPU首先到內存n 4的地方取出服務程序的地址aaaa:bbbb;然后將標志寄存器、中斷時的CSIP壓入堆棧,接著轉移到aaaa:bbbb處執行;在服務程序最后遇到iret的時候,CPU從堆棧中標志寄存器,然后取出CSIP并返回。

             

            在保護模式下,中斷或異常處理往往從用戶代碼切換到操作系統代碼中執行。由于保護模式下的代碼有優先級之分,因此出現了從優先級低的應用程序轉移到優先級高的系統代碼中的問題,如果優先級低的代碼能夠任意調用優先級高的代碼,就相當于擁有了高優先級代碼的權限。為了使高優先級的代碼能夠安全地被低優先級的代碼調用,保護模式下增加了門的概念。

             

            門,指向某個優先級高的程序所規定的入口點,所有優先級低的程序調用優先級高的程序只能通過門重定向,進入門的規定的入口點。這樣可以避免低級別的程序代碼從任意位置進入優先級高的程序的問題。

             

            保護模式下的中斷和異常等服務程序也要從門進入,80386的門分為中斷門、自陷門和任務門幾種。

             

            在保護模式下要表示一個中斷或異常服務程序的信息需要用8個字節,包括門的種類以及xxxx:yyyyyyyy格式的入口地址等。這組信息叫做中斷描述符。這樣,中斷向量表就無法采用和實模式下同樣的4字節一組的格式。

            保護模式下把所有的中斷描述符放在一起組成“中斷描述符表”IDTInterrupt Descriptor Table)。IDT不再放在固定的地址00000h處,而是采用可編程設置的方式,支持的中斷數量也可以設置。為此80386處理器引入了一個新的48位寄存器IDTRIDTR的高32位指定了IDT在內存中的基址(線性地址),低16位指定了IDT的長度,相當于指定了可以支持的中斷數量。

             

            保護模式下發生異常或中斷時,處理器先根據IDTR寄存器得到中斷描述符的地址,然后取出n號中斷/異常的門描述符,再從描述符中得到中斷服務程序的地址xxxx:yyyyyyyy,經過段地址轉換后得到服務程序的32位線性地址并轉移后執行。

             

            由于保護模式下用中斷門可以從低優先級的代碼調用高優先級的代碼,所以不能讓用戶程序寫中斷描述符表,否則會引發安全問題(CIH病毒)。這樣就如同關了窗子擋住蒼蠅,也擋住了微風,用戶的系統擴展程序也就不能像在DOS中一樣再用中斷服務程序的方式提供服務了。因為用戶程序根本沒有權限將中斷地址指到自己的代碼中來。

             

             

            Windows中,操作系統使用動態鏈接庫來代替中斷服務程序提供系統功能,所以Win32匯編中int指令也就失去了存在的意義。這就是在Win32匯編源代碼中看不到int指令的原因。其實那些調用API的指令原本是用int指令實現的。

             

             

            80386的保護機制

            80286之前的處理器只支持單任務,操作系統并沒有什么安全性可言,計算機的全部資源包括操作系統的內部都可以任憑程序員調用。

            但對于多任務的操作系統,某個搗亂的程序的為所欲為令即可使所有程序都無法運行。

            所以80286及以上的處理器引入了優先級的概念。80386處理器共設置4個優先級(0~3)。0級是最高級(特權級);3級是最低級(用戶級);1級和2級介于它們之間。特權級代碼一般是操作系統的代碼,可以訪問全部系統資源;其他級別的代碼一般都是用戶程序,可以訪問的資源受到限制。

             

            80386采用保護機制主要為了檢查和防止低級別代碼的越權操作,如訪問不該訪問的數據、端口以及調用高優先級的代碼等。保護機制主要由下列幾方面組成:

            1)段的類型檢查——段的類型是由段描述符指定的,主要屬性有是否可執行,是否可讀和是否可寫等。而CSDSSS等段選擇器是否能裝入某種類型的段描述符是有限制的。如不可執行的段不能裝入CS;不可讀的段不能裝入DSES等數據段寄存器;不可寫的段不能裝入SS等。如果段類型檢查通不過,則處理器會產生一般性保護異常或堆棧異常。

             

            2)頁的類型檢查——除了可以在段級別上指定整個段是否可以讀寫外,在頁表中也可以為每個頁指定是否可寫。對特權級下的執行代碼,所有的頁都是可寫的。但對123級的代碼,還要根據頁表中的R/W項決定是否可寫,企圖對只讀的頁進行寫操作會產生頁異常。

             

            3)訪問數據時的級別檢查——優先級低的代碼不能訪問優先級高的數據段。

                   80386的段描述符中有一個DPL域(描述符優先級),表示這個段可以被訪問的最低優先級。而段選擇器中含有RPL域(請求優先級),表示當前執行代碼的優先級。只有DPL在數值上大于或等RPL值的時候,該段才是可以訪問的,否則會產生一般性保護異常。

             

            4)控制轉移的檢查——在處理器中,有很多指令可以實現控制轉移,如jmpcallretintiret等指令。但優先級低的代碼不能隨意轉移到優先級高的代碼中,所以遇到這些指令的時候,處理器要檢查轉移的目的位置是否合法。

             

            5)指令集的檢查——有兩類指令可以影響保護機制。

                   第一類是改變GDTLDTIDT以及控制寄存器等關鍵寄存器的指令,稱為特權指令;       第二類是操作I/O端口的指令以及clisti等改變中斷允許的指令,稱為敏感指令。試想一下,如果用戶程序可以用sti禁止一切中斷(包括時鐘中斷),那么整個系統就無法正常運行,所以這些指令的運行要受到限制。特權指令只能在優先級0上才能運行,而敏感指令取決于eflags寄存器中的IOPL位。只有IOPL位表示的優先級高于當前代碼段的優先級時,指令才能執行。

             

            6I/O操作的保護——I/O地址也是受保護的對象。因為通過I/O操作可以繞過系統對很多硬件進行控制。80386可以單獨為I/O空間提供保護,每個任務有個TSS(任務狀態段)來記錄任務切換的信息。TSS中有個I/O允許位圖,用來表示對應的I/O端口是否可以操作。某個I/O地址在位圖中的對應數據位為0則表示可以操作;如果為1則還要看eflags中的IPOL位,這時只有IOPL位表示的優先級高于等于當前代碼段的優先級,才允許訪問該I/O端口。

             

             

            Windows的保護機制

            Windows下,操作系統運行于0行,應用程序運行于3級。因為Alpha計算機只支持兩個優先級,為了便于將應用程序移植到Alpha計算機上,Windows操作系統不使用12級這兩個優先級。

             

            Windows操作系統充分利用80386的保護機制,所有和操作系統密切相關的東西都是受保護的。運行于優先級3上的用戶程序有很多限制,只有在寫VxD等驅動程序的時候才可以使用全部資源。在Win32匯編編程中要注意避免以下的越權操作(當然寫驅動程序不在此列):

             

            1)顯而易見,所有的特權指令都是不可執行的,如lgdtlldtlidt指令和對CRxTRx等寄存器賦值。但是,讀取重要寄存器的指令是可以執行的,如sgdtsldtsidt等。

             

            2Windows在頁表中把代碼段和數據段中的內存賦予不同的屬性。代碼段是不可寫的,數據段中也只有變量部分的頁面是可寫的。所以雖然可以尋址所有的4GB空間,但訪問越出權限規定以外的東西還是會引發保護異常。

             

            3)在Windows 98中,系統硬件用的I/O端口是受保護的,但其余的則可以操作。如果用戶在機器中插入一塊自己的卡,用的是300h系統未定義的端口,那么在應用程序中就可以直接操作,但要操作3f8h(串口)和1f0h(硬盤端口)等系統已定義的端口就不行了。在Windows NT中,任何的端口操作都是不允許的。

             

            如果違反了Windows規定的“保護條例”,那么會引發保護異常,處理器會毫不猶豫地把控制權轉移到對應的異常處理程序中去。Windows會在處理程序中用一個很酷的“非法操作”對話框把用戶的程序判死刑,沒有一點回旋的余地!在Windows 9x中,系統有時會用一個藍屏幕來通知用戶程序試圖訪問不存在的內存頁。

             

            如果程序調用的DLL中有錯,那么錯誤還是會算在應用程序頭上,因為DLL的地址空間是被映射到應用程序的空間中去的。Windows 9x本身是32位和16位混合的操作系統,為了兼容DOSWin16程序,很多的保護措施做起來力不從心。所以系統內部反而常常出現越權操作,以至于藍屏幕不斷,這些就不是用戶應用程序自己的問題了。

             

            posted on 2010-08-06 13:42 luqingfei 閱讀(2120) 評論(1)  編輯 收藏 引用 所屬分類: Win32匯編程語言序設計

            評論

            # re: Win32匯編--需要了解的基礎知識 2014-04-23 02:28 solq

            哇,哥,連書里的內容都打上了,這花了不少時間吧
            。。。。。。  回復  更多評論   

            導航

            <2010年8月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            統計

            留言簿(6)

            隨筆分類(109)

            隨筆檔案(105)

            Blogers

            Game

            Life

            NodeJs

            Python

            Useful Webs

            大牛

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲一级Av无码毛片久久精品| 亚洲人成无码www久久久| 久久午夜无码鲁丝片| 精品国产乱码久久久久久1区2区| 久久青青草原综合伊人| 国产精品激情综合久久 | 新狼窝色AV性久久久久久| 久久人人爽人人爽人人AV| 97久久久久人妻精品专区| 亚洲国产成人久久综合野外| 久久久久亚洲av无码专区导航| 国产精品va久久久久久久| 中文字幕久久精品无码| 久久99精品久久久久久噜噜| 少妇内射兰兰久久| 久久久中文字幕日本| 国产精品久久网| 亚洲乱码精品久久久久..| 久久久久久国产精品无码下载 | 久久婷婷五月综合国产尤物app| 99久久精品影院老鸭窝| 99久久精品免费看国产一区二区三区| 国产精自产拍久久久久久蜜| 色欲综合久久中文字幕网| 久久综合亚洲色HEZYO社区 | 久久99国产精品成人欧美| 三上悠亚久久精品| 99久久综合国产精品免费| 久久精品一区二区三区中文字幕 | 久久久久亚洲AV成人网人人网站| 久久精品国产亚洲av水果派 | 亚洲国产精品18久久久久久| 亚洲欧美日韩久久精品| 久久激情亚洲精品无码?V| 97久久精品人人做人人爽| 99精品国产在热久久| 久久狠狠高潮亚洲精品| 99久久精品午夜一区二区| 久久久国产精品亚洲一区 | 久久艹国产| 久久五月精品中文字幕|