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