1 本章總述
-
通過讓編譯器產生機器級程式的匯編表示, 學習了編譯器及其優化能力, 以及機器、資料型別和指令集;
-
學習了程式如何將資料存盤在不同的記憶體區域中 —— 程式開發人員需要知道一個變數是存盤在運行時堆疊中, 亦或是在某個動態分配的資料結構中, 還是全域程式資料的一部分;
-
程式是以指令序列來表示的, 每條指令都完成一個單獨的操作; 部分程式狀態, 比如暫存器和運行時堆疊, 對程式開發人員來說是直接可見的;
-
編譯器必須使用多條指令來產生和操作各種資料結構, 以及實作包括條件、回圈和程序等在內的控制結構;
2 擴展內容
(1) C 語言中缺乏邊界檢查, 這就是的許多程式容易出現緩沖區溢位 —— 容易受到惡意入侵和攻擊.
(2) 編譯 C++ 和 C 的區別:
C++ 的早期實作只是簡單地執行了從 C++ 源到 C 源的轉換, 并對結果運行 C 編譯器, 產生目標代碼;
C++ 的物件用結構來表示, 類似于 C 中的struct;
C++ 的方法使用指向實作方法的代碼的指標來表示的.
(3) Java 的編譯方式:
Java 的目標代碼是一種特殊的二進制表示 —— Java 位元組碼 —— 可以看作是虛擬機的機器級程式;
Java 用位元組碼作為程式的低級表示, 優勢是: 相同的代碼可以在許多不同的機器上執行, 只需要在不同的機器上安裝 Java 虛擬機(JVM)即可;
Java 中還有一種稱為 即時編譯(Just-In-Time Compilation) 的方法, 動態地把位元組代碼序列翻譯成機器指令, 當代碼要執行多次時(比如在回圈中), 這種方法執行起來更快.
需要注意的是: Java 虛擬機并不是直接用硬體實作的, 而是用軟體解釋器處理位元組碼, 模擬虛擬機的行為.
====== 華麗的分割線 - 第三章第三周作業 - ======
3 一些總結性的知識
gcc-S生成匯編代碼,objdump -d反匯編程式, 生成可執行檔案后, 檔案變大 —— 因為包括了啟動、終止程式資訊, 以及作業系統互動資訊.
3.1 機器級編程二種重要的抽象
(1) 指令集體系結構, 定義了處理器狀態、指令的格式, 以及每條指令對狀態的影響.
(2) 機器級程式使用的存盤器地址是虛擬地址, 作業系統負責管理虛擬地址空間, 并將虛擬地址翻譯成實際處理器存盤器的物理地址.
3.2 IA32包含8個存盤32位值的暫存器
(1) %eax、%edx、%ecx稱為呼叫者保存暫存器, 程序P呼叫Q, Q可以覆寫他們.
(2) %ebx、%esi、%edi稱為被呼叫者暫存器, Q須在覆寫前保存, 并在回傳前恢復.
(3) 堆疊指標%esp始終保存著堆疊頂元素的地址, 壓堆疊減小堆疊指標, 堆疊向下增長; 幀指標%ebp, 大多數資訊的訪問都是相對于幀指標的.
3.3 MOV類中指令將源運算元復制到目的運算元
源運算元指定一個立即數, 存盤在暫存器或存盤器中,目的運算元指定一個位置,暫存器或存盤器地址,
(1) 有效地址: 立即數偏移Imm+基址暫存器R[Eb]+變址暫存器R[Ei]*比例因子s(1、2、4);
(2) 限制是兩個運算元不能同時指向存盤器位置;
(3) MOVS和MOVZ將較小的源資料復制到較大的資料位置, 高位符號擴展或零擴展.
4 堆疊幀結構
4.1 總體描述
IA32的程式使用堆疊支持程序的呼叫 (函式的呼叫), 在函式呼叫時會專門從堆疊中分出一塊記憶體 (稱為幀) 供函式使用.
傳遞給函式的引數由堆疊來保存, 幀則負責存盤暫存器的狀態、區域變數的記憶體分配的相關任務.
如果說函式P呼叫函式Q, 那么稱P為呼叫者 (caller), Q是被呼叫者 (callee).
根據上述規則, 堆疊會給Q分配幀, 并且用兩個指標 (分別存盤在%ebp%ebp和%esp%esp中) 指示幀的開始和結束的位置.
4.2 其他特性
(1) 堆疊規則提供了一種機制, 每次函式呼叫都有它自己私有的狀態資訊 (保存的回傳位置、堆疊指標和被呼叫者保存暫存器的內容), 因此每次遞回其實就是一個堆疊深度不斷增加的程序.
(2) 訪問陣列元素: movl (%edx, %ecx, 4), %eax 通過首地址+偏移量得到實際地址訪問;
(3) 讀存盤器比寫存盤器容易得多, 因此將只讀變數溢位到存盤器是合適的 —— 暫存器數量有限, 因此才會溢位到存盤器.
(4) 資料對齊的優點:
(a) 對齊限制簡化了形成處理器和存盤器系統之間的硬體設計;
(b) 嚴格對齊后, 可用一個存盤器用作讀或寫;
(c) 對齊資料以提高系統的性能.
(5) 指標的強制轉換, 只是改變在記憶體中的解讀方式. —— 很重要的一個理解.
5 對抗緩沖區溢位攻擊的幾種方式
(1) 堆疊隨機化;
(2) 堆疊破壞檢測: 利用一個金絲雀值完成;
(3) 限制可執行代碼區域: 只保存編譯器產生的代碼的那部分存盤器是可執行的, 其他部分可以被限制為只讀、只寫.
未完待續...
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/6655.html
標籤:其他
