OS之路第六章 --- 12.11日學習總結
1. equ是一個程式碼替換指令
equ 作用類似於 define。
str_len equ $-str
語句的意思:str-0 則是str字串的長度,用str_len來代替
2.C語言extern關鍵字的用法
修飾符extern用在變數或者函式的宣告前,用來說明“此變數/函式是在別處定義的,要在此處引用”。
函式宣告的作用是: 一方面告訴編譯器該函式的引數所需要的棧空間大小及返回值,這樣編譯器能為其準備好執行環境:另一方面如果該函式是在外部檔案中定義的,一定要在連結階段時將其對應的目標檔案一塊連結進來。
其主要是用作在一個檔案中引用另一個檔案的內容,使用方法如下:
main.c
#include<stdio.h>
int main()
{
extern const int num;
printf("%d",num);
return 0;
}
a.c
#include<stdio.h>
const int num = 5;
void func()
{
printf("fun in a.c");
}
3.在彙編程式碼中匯出符號供外部引用是用的關鍵字 global,引用外部檔案的符號是用的關鍵宇 extern 。
• 在 C 程式碼中只要將符號定義為全域性便可以被外部引用(一般情況下無需用額外關鍵宇修飾),引用外部符號時用 extern 宣告即可。
4.#ifndef的介紹
這是"if not defined"的簡寫,是巨集定義的一種,它是可以根據是否已經定義了一個變數來進行分支選擇,一般用於除錯等等。
作用:
- 防止標頭檔案的重複包含和編譯
- 便於程式的除錯和移植
#ifndef x //先測試x是否被巨集定義過
#define x
程式段1 //如果x沒有被巨集定義過,定義x,並編譯程式段 1
#else
程式段2 //如果x已經定義過了則編譯程式段2的語句,“忽視”程式段 1。
#endif//終止if
5.不能直接把立即數送入段選擇子中
6.global put_char
通過關鍵字 global 把函式 put_char 匯出為全域性符號,這樣對外部檔案便可見了,外部檔案通過宣告便可以呼叫。
7.PUSHAD 是 push all double,該指令壓入所有雙字長的暫存器,這裡的“所有” 一共是 8 個,它們的入棧先後順序是 EAX->ECX->EDX->EBX-> ESP-> EBP->ESl->EDI, EAX 是最先入棧。
8.往埠讀或寫資料
當往埠是獨立編址的時候,就不能把它當作記憶體使用,所以就不能用mov指令。因此CPU提供了一個專門的指令:in和out
in指令用於從埠中讀取資料,其一般形式為:
(ps:這是intel組合語言形式,目的運算元=源運算元)
(1)in al,dx
(2)in ax,dx
其中al和ax用來儲存從埠獲取的資料,dx是指埠號
out指令用於往埠中寫入資料,其一般形式為:
(1) out dx,al;
(2) out dx,ax;
(3) out 立即數,al;
(4)out 立即數,ax;
9.字元在視訊記憶體中佔 2 位元組,低位元組是 ASCII 碼,高字元是屬性
10.cld,字串“搬運”指令movs[bwd]和rep三劍客組合 完成大資料的複製。
cld 指令清除方向位,就是把 eflags 暫存器中方 向標誌位DF (DirectionFlag)清0。
11.
使用者程序是需要用 iretd中斷返回指令上 CPU 執行的。CPU 在執行 iretd 指令時會做特權檢查,它檢查 DS、 ES、 FS、 GS “資料”段暫存器的內容,這裡的資料加了引號,它用來指除程式碼段暫存器 cs 和堆疊段暫存器 SS 之外的段暫存器。在 32位保護模式下它們中儲存的都是選擇子。
要是有任何一個段暫存器所指向的段描述符的 DPL 許可權高於從 iretd命令返回後的 CPL ( 這個返回後的 CPL 也就是新的 CPL。 CPL 就是載入到 cs 暫存器中選擇子 的 RPL), CPU 就會將該段暫存器賦值為 0。
一旦將來用該段暫存器訪問記憶體時,由於選擇子為 0,這表示選擇子中的索引位、TI位和 RPL 位都為 0,所以會在 GDT 中檢索到第 0 個段描述符,由於第 0 個段描述符是空的不可用(這是 Intel有意為之的,為避免忘記初始化選擇子而誤選到了 GDT 中的第 0個描述符),這就會導致CPU丟擲異常。