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

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

2019-2020-1 20209313《Linux核心原理與分析》第二週作業 ================== # 零、總結 闡明自己對“計算機是如何工作的”理解。 計算機將資料和指令以二進位制的形式儲存於儲存介質上,通過馮諾依曼計算機模型,實現有限次計算,從而實現一定功能,滿足人類的需求。 通過整合封裝,實現從而降低工作的複雜度。(比如核心等整合的服務) 通過語言的多級抽象,從而以接近自然語言的方式方便人類程式設計,通過編譯和彙編等翻譯為機器語言,提高了程式設計人員生產力。 # 一、myod ## 步驟 1. 複習c檔案處理內容 2. 編寫myod.c 用myod XXX實現Linux下od -tx -tc XXX的功能 3. main與其他分開,製作靜態庫和動態庫 4. 編寫Makefile 5. 提交測試程式碼和執行結果截圖, 提交除錯過程截圖,要全屏,包含自己的學號資訊 6. 在部落格園發表一篇部落格,重點寫遇到的問題和解決過程 ##總結 1. 問題:命名修改導致不停輸錯命令 解決:進行命名管理;使用批量替換修改 2. 問題:ld: attempted static link of dynamic object ![](https://img2020.cnblogs.com/blog/2175053/202010/2175053-20201018231742813-963558810.png) 解決: - 因為指定了連結引數-static,它的存在,要求連結的必須是靜態庫,而不能是共享庫 - 連結的應該為其他函式,誤寫成main函式的目標檔案了 3. 問題:undefined reference to異常 解決:因為makefile寫錯了,把連結庫的名字寫成要呼叫它的檔名了,導致找不到檔案 4. 問題:使用檔案時,找不到動態庫 解決:gcc編譯時指明路徑 ./ ![](https://img2020.cnblogs.com/blog/2175053/202010/2175053-20201018232311305-1996030528.png) 其他方法:來源於https://www.cnblogs.com/x_wukong/p/4722903.html 分析原因:ld提示找不到庫檔案,而庫檔案就在當前目錄中。 連結器ld預設的目錄是/lib和/usr/lib,如果放在其他路徑也可以,需要讓ld知道庫檔案在哪裡。 - 方法1: 編輯/etc/ld.so.conf檔案,在新的一行中加入庫檔案所在目錄; 執行ldconfig,以更新/etc/ld.so.cache檔案; - 方法2: 在/etc/ld.so.conf.d/目錄下新建任何以.conf為字尾的檔案,在該檔案中加入庫檔案所在的目錄; 執行ldconfig,以更新/etc/ld.so.cache檔案; 覺得第二種辦法更為方便,對於原系統的改動最小。因為/etc/ld.so.conf檔案的內容是include /etc/ld.so.conf.d/*.conf 所以,在/etc/ld.so.conf.d/目錄下加入的任何以.conf為字尾的檔案都能被識別到。 # 二、C程式反彙編 1. 目的:分析彙編程式碼的工作過程中堆疊的變化 2. 基本知識: ## X86t體系結構棧地址向下增長(地址減小) ## 彙編指令: ### mov定址 ``` 1. 暫存器定址 movl %eax, %edx 2. 立即定址 movl $0x123, %edx 3. 直接定址 movl 0x123, %edx 4. 變址定址 movl 4(%ebx), %edx ``` ### 進出棧 1. 進棧 ``` pushl %eax 等價偽指令 sub $4 ,%esp mov %eax,%esp 2.出棧 popl %eax 等價偽指令 mov %esp,%eap add $4 ,%esp 3.函式命令 - 函式呼叫 call 0x12345 等價偽指令 push %eip mov $OX???? ,%eip - 函式返回 ret 等價偽指令 pop %eip - 建立函式堆疊enter 等價偽指令 push1 %ebp movl %esp, %ebp - 撤銷函式堆疊leave 等價偽指令 movl %ebp, %esp popl %ebp ``` 3. 步驟一 反彙編 ``` // main.c int g(int x) { return x + 5555; } int f(int x) { return g(x); } int main(void) { return f(6) + 6666; } ``` ![](https://img2020.cnblogs.com/blog/2175053/202010/2175053-20201018232126107-1250148043.png) ![](https://img2020.cnblogs.com/blog/2175053/202010/2175053-20201018232042662- 4. 步驟二 分析彙編程式碼 ``` g: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax addl $5555, %eax popl %ebp ret f: pushl %ebp movl %esp, %ebp subl $4, %esp movl 8(%ebp), %eax movl %eax, (%esp) call g leave ret main: pushl %ebp movl %esp, %ebp subl $4, %esp movl $6, (%esp) call f addl $6666, %eax leave ret ``` (二)下面分析過程 ``` 首先進行main函式呼叫g: main: // 1、建立main的空棧 等價於enter pushl %ebp movl %esp, %ebp // 2、等價於push $6 subl $4, %esp //棧頂地址-4,左移增加棧空間一個單元 movl $6, (%esp) //棧頂值設為6(設在記憶體中對應塊號為0) //(設該立即數的儲存位置在記憶體中對應塊號為0) // 3、進入f函式呼叫 call f //eip跳轉到函式f的第一條命令 f: // 1、壓棧f所需引數(上一步的棧頂值即為引數,放在f的棧底) // 建立f的空棧 等價於enter pushl %ebp //基地址右移一個單元(在記憶體中對應塊號為1),獲取塊號0的值,放在eax。 movl %esp, %ebp //棧頂、棧底指向(在記憶體中對應塊號為1),建立f的空棧 // push f棧的-2單元 subl $4, %esp //左移,增加棧空間一個單元(esp在記憶體中對應塊號為2) movl 8(%ebp), %eax//獲取(基地址塊號1右移兩個單元,在記憶體中對應塊號為-1)即上級函式儲存的立即數6,放到eax // 將值存入f的棧頂 movl %eax, (%esp)//塊號2儲存塊號0的儲存值) // 2、 進入g函式呼叫 call g //eip跳轉到函式g的第一條命令 g: // // 建立g的空棧 等價於enter pushl %ebp //(ebp儲存的地址對應在記憶體中對應塊號為2) movl %esp, %ebp//(esp儲存的地址對應在記憶體中對應塊號為2) // 上級函式所給的引數6 +5555儲存到eax(存著main所給的引數值6) movl 8(%ebp), %eax//獲取(在記憶體中對應塊號為0)儲存值.即上級函式儲存的立即數6,放到eax addl $5555, %eax // eax暫存器值加5555 popl %ebp //ebp指向塊號為1,塊號2的地址 // 返回上級函式f,返回值為eax的值 ret //撤銷g的空堆疊 leave // 返回上級函式main,返回值為eax的值 ret addl $6666, %eax // eax暫存器值加56666 leave //撤銷空堆疊 // main函式結束,返回值為eax的值 ret ``` # 三、其他 ``` ## 除錯 * b 設斷點(要會設4種斷點:行斷點、函式斷點、條件斷點、臨時斷點) * run 開始執行程式 * bt 列印函式呼叫堆疊 * p 檢視變數值 * c 從當前斷點繼續執行到下一個斷點 * n 單步執行 * s 單步執行 * quit 退出CGDB ## 四種斷點的設法 1.條件斷點:b fxx(函式名) 2.條件斷點:b 12 if i=5000 3.行斷點:b 行號 4.臨時斷點:tb 行號 # gcc編譯 ### 預處理 gcc -E hello.c -o hello.i ### 編譯 gcc –S hello.i –o hello.s ### 彙編 gcc –c hello.s –o hello.o ### 連結 gcc hello.o –o hello.exe # gcc打包 1.把程式碼編譯為目標檔案形式(形如): gcc -c liberr.c -o liberr.o ## 靜態庫 2.使用工具ar建立一個存檔檔案: ar rcs mymath9313.a otherfunc.o 3.編譯程式時把程式和myod9313.a連結起來: gcc -static -o myod XXX myod9313.o mymath.a ## 動態庫 1.建立一個共享目標檔案 gcc -shared -fpic -o mymath.so add5320.c sub5320.c mul.c div.c gcc -shared -fpic -o myod9313.so myod9313.c 2.建立可執行目標檔案 gcc -o myod XXX myod9313.c ./mymath.so ## 執行+測試 ## makefile myod XXX:main.o otherfunc.o s gcc main.o otherfunc.o s -o testmyod main.o:main.c gcc -c main.c -o main.o otherfunc.o:otherfunc.c gcc -c otherfunc.c -o otherfunc.o clean: rm -f *.o testmymath