1. 程式人生 > >2018-2019-1 20189206 《Linux核心原理與分析》第二週作業

2018-2019-1 20189206 《Linux核心原理與分析》第二週作業

Linux核心分析 第二週學習


知識總結

作業系統與核心

  • 作業系統 指在整個系統中負責完成最基本功能和系統管理的那些部分
  • 核心 實際是作業系統的內在核心
    • 核心獨立於普通應用程式,擁有受保護的記憶體空間和訪問硬體裝置的所有許可權,這種空間被稱為核心空間
    • 當核心執行的時候,系統以核心狀態進入核心空間執行
    • 當應用程式通過系統呼叫與核心通訊時,我們稱核心正在代其執行
      • 應用程式稱為通過系統呼叫在核心空間執行,核心被稱為運行於程序上下文中
      • 實際上,應用程式通常呼叫庫函式,然後庫函式通過系統呼叫介面,讓核心完成不同任務
    • linux是一個單核心,但擁有模組化設計、搶佔式核心、支援核心執行緒及動態裝載核心模組的能力

計算機工作原理

馮諾依曼體系結構

根據馮諾依曼提出的理論:把程式本身當作資料來對待,程式和資料處理用同樣的方式

  • CPU 是計算機硬體的基礎,與記憶體和I/O裝置進行互動,其中PC程式暫存器總是指向下一條要執行的命令
    • API 程式與計算機的介面
    • ABI 程式與CPU的介面

      x86-32彙編基礎

      CPU的暫存器
      8086CPU中一共有14個16位暫存器,分別為:
  • 資料暫存器
    • AX 累加暫存器
    • BX 基地址暫存器
    • CX 計數器暫存器
    • DX 資料暫存器
  • 指標暫存器
    • SP 堆疊指標暫存器
    • BP 基指標暫存器
  • 變址暫存器
    • SI 源變址暫存器
    • DI 目的變址暫存器
  • 控制暫存器
    • IP 指令指標暫存器
    • FLAG 標誌暫存器
  • 段暫存器
    • CS 程式碼段暫存器
    • DS 資料段暫存器
    • SS 堆疊段暫存器
    • ES 附加段暫存器
      【注】在32位CPU中,32位暫存器EAX EBX ECX EDX 不僅可以傳送資料、暫存資料儲存算數羅運算結果,還可以作為指標暫存器。
      在定位一個指令時,使用CS:EIP來指明它的地址
定址方式和常用匯編指令
  • 運算元
    • 立即數 即常數,用$後跟一個數值表示
    • 暫存器數 表示某個暫存器儲存的值 用%eax表示
    • 儲存器引用 根據計算出來的有效地址,訪問儲存器的某個位置
  • 常見彙編指令
    • 暫存器定址 操作暫存器而不和記憶體打交道
      • movl %eax,%edx 表示將暫存器eax中的內容放到ebx中
    • 立即定址
      • movl $0x123, %eax 表示將0x123這個16進位制數放入eax這個暫存器中
    • 直接定址
      • movl 0x123,%edx 表示將0x123記憶體地址所指向的那塊記憶體裡儲存的資料放到EDX暫存器中
    • 間接定址
      • movl (%ebx),%edx 表示取ebx暫存器中儲存的地址的值,放入edx中
    • 變址定址
      • movl 4(%ebx),%edx 表示在間接定址的基礎上,在原地址上加上一個立即數4
    • 出棧入棧
      • pushl %eax
        • 相當於subl $4,%esp movl %eax,(%esp)將棧頂指標向下移動一位,再將eax的內容放入esp指向的記憶體中
        • 由於堆疊是向下增長的,所以用減指令棧頂指標向下移動
      • popl %eax
        • 相當於movl (%esp),%eax addl $4,%esp 將棧頂數值放在eax暫存器中,esp指標向上移動,棧在收縮
    • 函式呼叫
      • call 0x12345
        • 相當於pushl %eip(*) movl $0x12345, %eip(*) 將當前eip(指向下一條要執行的指令地址)入棧,然後將新的地址賦給eip
        • 由於不能直接對eip進行操作,所以以上的等價操作都是偽指令
    • 函式返回
      • ret
        • 相當於popl %eip(*) 就是把當前堆疊棧頂的一個儲存單元放到eip暫存器中
    • 巨集指令
      • leave 用來撤銷函式堆疊
        • 相當於movl %esp,%ebp popl %ebp
      • enter 用來建立函式堆疊

        • 相當於pushl %ebp movl %esp,%ebp

實驗部分

實驗一 反彙編一個簡單的C程式

通過linux系統的gcc編譯命令的引數-S 編譯出彙編程式main.s 利用vim檢視其中的程式碼。

其中,產生的彙編程式碼中所有以.開頭的命令都是用於連結的輔助資訊,為了檢視到純彙編程式,我們可以將所有帶點的命令刪除,得到的就是彙編程式碼。

對彙編程式碼的分析

  • pushl %ebp ebp指標指向棧底,將ebp指向的位置入棧,棧頂指標esp向下移動
  • movl %esp , %ebp ebp和esp指向同一個位置
    上面兩條命令相當於建立main函式自己的函式呼叫空間
  • subl $4,%esp esp指標減4 表示指標向下移動一個位置
  • movl $2,(%esp) 將立即數2存入esp指向的位置
  • call f 相當於 pushl %eip
    movl f,%eip 實際上就是將eip指標指向的程式碼地址入棧,之後將eip指標指向f函式,實現了函式的跳轉
    之後再跳轉執行f函式的程式碼。

【注】EAX暫存器是預設儲存函式返回值的暫存器
所有函式的頭兩行指令用於初始化函式自己的函式呼叫堆疊空間

對應的堆疊變化




遇到的問題

  1. movl %eax,%ebx 是將eax暫存器中儲存的內容給了ebx
    movl %esp,%ebp 是將ebp指標指向和esp指標指向的同一個位置
    我剛開始就對這兩條命令不是很清楚,為什麼第一條就可以是儲存內容,而第二條就是改變了指標的指向。後來我反應過來,esp和ebp這兩個暫存器儲存的是地址,是堆疊的棧底和棧頂的位置,從實質來看,改變的仍舊是暫存器中的內容。

2.剛開始的堆疊總是畫不對,後來發現是概念錯誤

pushl %esp 首先將esp指標向下移動一位,再將esp指向的地址入棧。