標籤:
電腦是如何工作的?
註:臧文君,原創作品轉載請註明出處,《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000
一、儲存程式電腦工作模型
1、馮諾依曼體繫結構:指儲存程式電腦
(1)硬體的角度:分為CPU+記憶體+匯流排
CPU中的一個寄存器---IP:Instruction Pointer,指向記憶體的CS:Code Segment
16位的CPU上叫IP,32位叫EIP,64位叫IIP
CPU通過IP從記憶體中取一條指令執行,執行過後,IP自加1,再取下一條指令執行
(2)程式員的角度:記憶體儲存指令和資料,CPU負責解釋和執行指令,兩者通過匯流排串連
2、API:程式員與電腦的介面介面 Application Program Interface
ABI:程式與CPU的介面介面,二進位的介面,主要是指令編碼 Application Binary Interface
二、X86彙編基礎
1、X86 CPU的寄存器
(1)通用寄存器
16-bit:AX,BX,CX,DX.BP,SI,DI,SP
32-bit:EAX,EBX,ECX,EDX.EBP,ESI,EDI,ESP
*注*:堆棧是電腦中非常基礎性的東西
(2)段寄存器:CS,DS,ES,SS,FS,GS
程式碼片段和堆棧段寄存器使用最多
CPU在實際取指令時根據cs:eip來準確定位一個指令
(3)標識寄存器:EFLAGS register
用於標識當前的狀態
*注*:X86_64 Registers寄存器,與32位的在核心機制上差別不大,其通用寄存器擴充成64位,前面標R。
2、X86彙編指令一(mov指令及幾種記憶體定址方式)
b--8位,w--16位,l--32位,q--64位
(1)寄存器定址register mode
以%開頭的寄存器標示符,與記憶體無關
例:movl %eax,%edx edx=eax;
(2)立即定址immediate
立即數是以$開頭的數值,與記憶體無關
例:movl $0x123,%edx edx=0x123; 0x:16進位
(3)直接定址direct
直接存取一個指定的記憶體位址的資料
例:movl 0x123,%edx edx=*(int32_t*)0x123;
這裡的0x123指記憶體位址為16進位數123,將該地址中的資料放到edx中
(4)間接定址indirect
將寄存器的值作為一個記憶體位址來訪問記憶體
例:movl (%ebx),%edx edx=*(int32_t*)ebx;
ebx這個寄存器存的值是一個記憶體位址,加()表示之歌記憶體位址儲存的資料
(5)變址定址displaced
變址定址在間接定址之時改變寄存器的數值
例:movl 4(%ebx),%edx edx=*(int32_t*)(ebx+4);
註:AT&T彙編格式與Intel彙編格式略有不同
Linux核心使用的是AT&T彙編格式
3、X86彙編指令二(push,pop,call,ret)
ebp--棧底,esp--棧底,棧是向下增長
push壓棧,pop彈棧
call函數呼叫堆疊,是理解C代碼在CPU上執行的關鍵
將當前的eip壓棧,再將其附一個新值
ret將call時儲存的eip值再還原到eip寄存器中
註:*代表這些指令不能被程式員直接使用,屬於偽指令,因為eip寄存器不能被直接修改,只能通過特殊指令間接修改
4、分析幾個彙編指令片段
(1)
分析:
(2)
分析:
(3)
分析:
三、彙編一個簡單的C程式分析其彙編指令執行過程
編譯語句:gcc -S -o -main.s main.c -m32
在編譯好的檔案中,所有以.開頭的內容都是用於連結時的輔助資訊,在實際中不會被執行,因此可以刪除,留下純彙編代碼。
enter將棧置為空白
leave撤銷函數堆棧
函數呼叫堆疊是由邏輯上多個堆棧疊加起來的
函數的傳回值預設使用eax寄存器儲存返回給上一級函數
四、實驗部分
在學習過了孟老師的視頻教學之後,實驗做起來相對容易一些。
1、我使用ls命令查看了目前的目錄下的檔案,進入Code/shiyanlou_cs195目錄下進行代碼編寫。
2、建立main.c檔案,編寫代碼,我將所給的樣本程式中的數值進行了修改。
3、儲存之後,使用gcc -S -o main.s main.c -m32命令產生組合語言檔案。
4、開啟main.s檔案,裡面是C程式對應的組合語言。
5、為了分析方便,將所有以.開頭的語句都刪除,我查了一下Linux環境下的命令,可以用dd直接刪除一行代碼,剩下的就是純彙編代碼。
6、分析
通過這次實驗,使我對如何反組譯碼一個C程式有了一定瞭解,使用gcc -S -o main.s main.c -m32命令,-m32主要是指產生32位的格式。另外,調用其它函數時,將指令指標入棧儲存,以便函數執行結束能返回來繼續下一條指令的執行,相當於push eip。函數參數入棧,參數入棧順序是從右至左進棧。函數退出時,將esp賦值給ebp,從而釋放當前函數所使用的棧空間。
五、總結
這次課程學習的內容主要圍繞電腦是如何工作的,學習了電腦的馮諾依曼體繫結構、X86 CPU寄存器、寄存器的定址方式和一些彙編指令,並通過實驗鞏固對知識的理解。
我覺得電腦的工作依靠的就是一條條彙編語句的執行,CPU通過IP從記憶體中取一條指令執行,在堆棧中根據指令找到相應地址,將其內容返回到記憶體中,然後IP自加1,再取下一條指令執行。組合語言是電腦可以識別的語言,因此我們理解起來沒有C語言那樣簡潔明了。所以我覺得在分析一段彙編代碼的時候,需要自己動手畫出堆棧的變化,從而準確清晰的瞭解每一步堆棧的變化。再如call、ret、enter、leave指令,我們要熟記他們對應的ip/bp/sp的操作變化,從而加快我們對代碼的分析。
作業1:電腦是如何工作的?20135115臧文君