2019-2020-1 20209313《Linux核心原理與分析》第二週作業
阿新 • • 發佈:2020-10-19
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