第五周学习报告
程序的機器級表示。
GCC C語言編譯器以匯編代碼的形式產生輸出,匯編代碼是機器代碼的文本表示,然后GCC調用匯編器和鏈接器,從而根據匯編代碼生成可執行的機器代碼。
一、歷史觀點
Linux使用了平坦尋址方式,使程序員將整個存儲空間看做一個大的字節數組。
二、程序編碼
將源代碼轉化成可執行代碼,C預處理器擴展源代碼。
1.機器碼代碼
兩種抽象:機器級程序的格式和行為,定義為指令集體系結構;二是機器級程序使用的存儲器地址是虛擬地址,提供的存儲器模型看上去是一個非常大的字節數組。
2.代碼示例
3.關于格式的注釋
三、數據格式
1、大多數常用數據類型都是以雙字形式存儲的。包括INT和LONG INT。
2、處理字符串數據時,通常會用到字節。
3、浮點數有三種形式:單精度值float,雙精度值double,和擴展精度。
4、大多數GCC生成的匯編代碼指令都有一個字符后綴,表明操作數的大小。
四、訪問信息
一個IA32中央處理單元CPU包含一組8個存儲32位值的寄存器。寄存器用來存儲整數數據和指針。
1.操作數指示符
各種不同的操作數的可能性被分為三種類型。第一種類型是立即數,也就是常數值。第二種類型是寄存器,它表示某個寄存器的內容,對雙字操作來說,可以是8個32位寄存器中的一個。第三類操作數是存儲器引用,它會根據計算出來的地址訪問某個存儲器地址。
2.數據傳送指令
把許多不同的指令分成了指令類,一類中的指令執行一樣的操作,只不過操作數大小不同。如 MOV中的指令將源操作數的值復制到目的操作數中。源操作數指定的值是一個立即數,存儲在寄存器中或者存儲器中。目的操作數指定一個位置,要么是一個寄存器,要么是一個存儲地址。而 PUSH指令的功能是把數據壓入到棧上,而 POPL指令是彈出數據。這些指令都只有一個操作數——壓入的數據源和彈出的數據目的。
因為棧和程序代碼以及其他形式的程序數據都是放在同樣的存儲器中,所以程序可以用標準的存儲器尋址方法訪問棧內任意位置。
3.數據傳送示例
五、算術和邏輯操作
給出的每個指令類都有對字節、字、和雙字數據進行操作的指令。這些指令被分為四組:加載有效地址、一元操作、二元操作和移位;二元操作有兩個操作數,而一元操作有一個操作數。
1.加載有效地址
加載有效地址指令LEAL實際上MOVL指令的變形。它的指令形式是從存儲器讀數據到寄存器,但是實際上它根本沒有引用存儲器。
目的操作數必須是一個寄存器。
2.一元操作和二元操作
第二組中的操作是一元操作,它只有一個操作數,既是源又是目的;第三組中操作是二元操作,其中第二個操作數既是源又是目的。
3.移位操作
最后一組是移位操作,先給出移位量,然后第二項給出的是要移位的位數。它可以進行算術和邏輯右移。移位量可以是單節編碼,還可以是一個立即數。移位操作數的目的操作數可以是一個寄存器,或者是一個存儲器位置。
4.討論
5.特殊的算術操作
六、控制
到目前為止,我們只考慮了直線代碼的行為,也就是指令一條接著一條順序的執行。機器代碼提供兩種基本的低級低制來實現有條件的行為:測試數據值,然后根據測試的結果來改變控制流或者數據流。
用JUMP指令可以改變一組機器代碼的執行順序;編譯器必須產生指令序列,這些指令序列構建在這種實現C語言控制結構的低級機制之上。
1.條件碼
除了整數寄存器,CPU還維護著一組單個位的條件碼寄存器。最常見的條件碼有CF、ZF、SF、OF;
LEAL指令不改變任何條件碼,因為它是用來進行地址計算的。
CMP指令和SUB指令的行為是一樣的。
TEST指令和AND指令的行為一樣的,除了他們只設置條件碼而改變目的寄存器的值。典型的用法,兩個操作數是一樣的,或者其中的一個操作數是一個掩碼,用來指示哪些位應該被測試。
2.條件訪問碼
條件碼通常不會直接讀取,常見的使用方法有:1.)可以根據條件碼的某個組合,將一個字節設置為0或者1;2.)可以條件跳轉到程序的某個其他的部分3.)可以有條件地傳送數據。
機器代碼對于有符號和無符號兩種情況都使用一樣的指令,這是因為許多的算術運算對無符號和補碼算術都有一樣的位級行為。
3.跳轉指令極其編碼
跳轉指令會導致執行切換到程序中一個全新的位置。
4.翻譯條件分支
將條件表達式和語句從C語言翻譯成機器代碼,最常用的方式是結合有條件和無條件跳轉。
5.循環
大多數匯編器根據一個循環的do-while形式來產生循環代碼。
6.條件傳送指令
實現條件操作的傳統方法是利用控制的條件轉移。數據的條件轉移是一種替代的策略。這種方法先計算一個條件操作的兩種結果,然后再根據條件是否滿足從而選取一個。
7.switch語句
選擇開關語句不僅僅提高C代碼的可讀性,而是通過使用跳轉表這種數據結構使得實現更加高效。
七、過程
一個過程調用包括將數據和控制從代碼的一部分傳遞到另一部分。另外,它必須在進入時為過程的局部分量分配空間,并在退出時釋放這些空間。數據傳遞和、局部變量的分配和釋放通過操縱程序棧來實現。
1.棧幀結構
IA32程序用程序棧來支持過程調用。機器用棧來傳遞過程參數、存儲返回信息、保存寄存器用于以后恢復,以及本地存儲。為單個過程分配的那部分棧為棧幀,棧幀的最頂端以兩個指針界定,寄存器%ebp為幀指針,而寄存器%esp為棧指針。當程序執行時,棧指針可以移動,因此大多數信息的訪問都是相對于幀指針的。(棧用來傳遞參數,存儲返回信息,保存寄存器,以及本地存儲)
2.轉移控制
CALL指令有一個目標,即指明被調用過程起始的指令地址。CALL指令的效果是將返回地址入棧,并跳轉到被調用過程的起始處。RET指令從棧中彈出地址,并跳轉到這個位置。
3.寄存器使用慣例
寄存器%eax,%edx和%ecx被劃分為調用者保存寄存器。當過程P調用Q時,Q可以覆蓋這些寄存器,而不會破壞任何P所需要的數據。另一方面,寄存器%ebx,%esi和%dei被劃分為被調用者保存寄存器。根據描述的慣例,必須保持寄存器%ebp和%esp。
4.過程示例
編譯器根據一組很簡單的慣例來產生慣例棧結構的代碼。參數在棧上傳遞給函數,可以從棧中用相對于%ebp的正偏移量,來訪問他們。可以用push指令或者是從棧指針減去偏移量來在棧上分配空間,在返回前,函數必須將?;謴偷皆紬l件,可以恢復所有的被調用者保存寄存器和%ebp,并且重置%esp使其指向返回地址。為了使程序能夠正確執行,讓所有過程都遵循一組建立和恢復棧的一致慣例很重要。
5.遞歸過程
八、數組分配和訪問
1.基本原則
2.指針運算
如果P是一個指向類型為T的數據的指針,P為值xp,那么表達式p+i的值為xp+L,這里L是指數據類型T的大小。
3.嵌套的數組
4.定長數組
5.變長數組
九、異質的數據結構
1.結構
2.聯合
3.數據對齊
十、綜合理解指針
十一、使用GDB調試器
通常的方法是在程序感興趣的地方附近設置斷點。斷點可以設置在函數入口后面,或者一個程序的地址處。在斷點處,可以單步追蹤程序,一次只執行幾條指令,或是前進到下一斷點。一些命令,如 kill-停止程序,break sum-在函數sum入口設置斷點。disas-反匯編當前函數。等。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
??
?
?
? ??
??
?
轉載于:https://www.cnblogs.com/java44/p/4869232.html
總結
- 上一篇: 行数溢出隐藏
- 下一篇: p2p银行存管是什么意思