鄭卓彬 + 原創作品轉載請注明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000
前言:
? ? 第一節課,老師講了馮諾依曼計算機的程序執行流程,以及部分匯編指令,和匯編代碼中的函數棧。
計算機程序運行:
? ? 馮諾依曼計算機,分為運算器、控制器、存儲器、輸入設備、輸出設備五部分。其中運算器、控制器就是計算機中的cpu,cpu中有寄存器、程序計數器。當程序在計算機中運行時,cpu中的ip寄存器存儲著下一條指令的地址,每當一條指令執行完,cpu就從ip寄存器中取出相應指令的地址進行解析執行,并且ip自動加一指向下一條需要執行指令的地址。
匯編基礎:
? ? 匯編語言是較為底層的語言,也是計算機指令與高級語言的接口,本章學習了基礎的匯編命令和8086cpu的各個寄存器作用。
寄存器作用:
匯編指令:
解析: ?mov指令,用于將 源 里的數據傳到 目的 ?其中該指令的源在 后面跟著的左半部分,目的在右半部分。 但是根據尋址模式的不同,會傳回不同的參數,如寄存器模式就是將前一個寄存器中的值傳入后一個寄存器,立即數尋址就是將該數字傳到目的等。
解析: ?如圖,左邊的一條指令就相當與右邊的多條指令。
實驗例子:
對于如下的c代碼 ? :
可用 gcc ?解析為中間文件,并將,將中間文件中的帶.開頭的句子刪除,就剩下這c程序對應的匯編代碼了:
對應匯編代碼:
匯編代碼如上,各個分段對應圖四的函數。
匯編代碼基礎:
1、每個函數的調用都會在該程序的棧中添加一個函數棧區,用來保存該函數的上下文。
2、ebp和esp寄存器:ebp寄存器指向該函數棧的棧底,且棧底的內容存儲的是上一個棧底的地址。esp的內容是棧頂的地址。
匯編代碼解析:
1、main函數:
? ? pushl %ebp ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? movl%esp, %ebp ? ? ? ? ? #以上兩條語句,將的ebp中的內容存到棧中做棧底,并把ebp重新指向該棧底
? ? subl$4,%esp
? ? movl$2,(%esp) ? ? ? ? ? ? ? ?#以上兩條語句將數2壓棧
? ? call f ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#調用f函數,是將eip中的值壓棧(函數調用回來后要執行的指令),并將f函數 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 的地址存入eip
? ? addl$3,%eax ? ? ? ? ? ? ? ? ? ?#將傳回的數與立即數3相加
? ? leave ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#將棧頂地址變為棧底地址,也就是使該棧成為空棧,并將ebp寄存器中的值改 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?為上個棧底
? ? ret ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#結束
2、f函數:
? ? pushl %ebp
? ? movl%esp, %ebp ? ? ? ? #以上兩條語句,將的ebp中的內容存到棧中做棧底,并把ebp重新指向該棧底
? ? subl$4,%esp
? ? movl8(%ebp), %eax ? ?
? ? movl%eax, (%esp)? ? ? #以上三條語句將main函數中壓棧的值2給取到eax寄存器中,并且將該值也壓到f ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 函數的棧中
? ? call g? ? ? ? ? ? ? ? ? ? ? ? ? ? #調用g函數,是將eip中的值壓棧(函數調用回來后要執行的指令),并將f函數 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 的地址存入eip
? ? leave ? ? ? ? ? ? ? ? ? ? ? ? ? ?#將棧頂地址變為棧底地址,也就是使該棧成為空棧,并將ebp寄存器中的值改? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 為上個棧底
? ? ret? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #將main函數壓棧的eip值返回到eip寄存器中,既繼續執行調用main函數的下面一 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?條指令
3、g函數:
? ? pushl %ebp
? ? movl%esp, %ebp ? ? #以上兩條語句,將的ebp中的內容存到棧中做棧底,并把ebp重新指向該棧底
? ? movl8(%ebp), %eax
? ? addl$1,%eax? ? ? ? ? ? #以上兩條語句將f函數中壓棧的值2給取到eax寄存器中,并且加一,用于返回
? ? popl %ebp ? ? ? ? ? ? ? ?#彈出f函數的棧底到ebp中
? ? ret? ? ? ? ? ? ? ? ? ? ? ? ? ? #將f函數壓棧的eip值返回到eip寄存器中,既繼續執行調用f函數的下面一條指令
總結:
? ? 我理解的計算機其實是很笨的,一直的動作就是取指令,運行,取指令,運行。計算機之所以能體現的較為智能,是程序員一步步迭代的過程,程序員將顯示生活中存在的實物或者抽象和邏輯用高級語言編寫出來。所以計算機其實是人的思想的體現,只是他能之分認真的執行工作,可以24小時執行且基本不出錯。
真實姓名(與最后申請證書的姓名務必一致) + 原創作品轉載請注明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000