目錄
第1部分 預備知識
第1章 十六進製計數法 3
1.1 二進製計數法迴顧 3
1.1.1 關於二進製計數法 3
1.1.2 二進製到十進製的轉換 4
1.1.3 十進製到二進製的轉換 4
1.2 十六進製計數法 5
1.2.1 十六進製計數法的原理 5
1.2.2 十六進製到十進製的轉換 6
1.2.3 十進製到十六進製的轉換 6
1.2.4 為什麼需要十六進製 6
1.3 使用Windows計算器方便你的學習過程 8
本章習題 9
第2章 處理器、內存和指令 10
2.1 最早的處理器 10
2.2 寄存器和算術邏輯部件 10
2.3 內存儲器 12
2.4 指令和指令集 14
2.5 古老的Intel 8086處理器 16
2.5.1 8086的通用寄存器 16
2.5.2 程序的重定位難題 16
2.5.3 內存分段機製 19
2.5.4 8086的內存分段機製 21
本章習題 24
第3章 匯編語言和匯編軟件 25
3.1 匯編語言簡介 25
3.2 NASM編譯器 27
3.2.1 NASM的下載和安裝 27
3.2.2 代碼的書寫和編譯過程 27
3.2.3 用HexView觀察編譯後的機器代碼 30
本章習題 31
第4章 虛擬機的安裝和使用 32
4.1 計算機的啓動過程 32
4.1.1 如何將編譯好的程序提交給處理器 32
4.1.2 計算機的加電和復位 33
4.1.3 基本輸入輸齣係統 33
4.1.4 硬盤及其工作原理 34
4.1.5 一切從主引導扇區開始 36
4.2 創建和使用虛擬機 37
4.2.1 彆害怕,虛擬機是軟件 37
4.2.2 下載和安裝Oracle VM VirtualBox 37
4.2.3 虛擬硬盤簡介 39
4.2.4 練習使用FixVhdWr工具嚮虛擬硬盤寫數據 40
第2部分 實模式
第5章 編寫主引導扇區代碼 45
5.1 本章代碼清單 45
5.2 歡迎來到主引導扇區 45
5.3 注釋 46
5.4 在屏幕上顯示文字 46
5.4.1 顯卡和顯存 46
5.4.2 初始化段寄存器 49
5.4.3 顯存的訪問和ASCII代碼 49
5.4.4 顯示字符 51
5.4.5 MOV指令的格式 52
5.5 顯示標號的匯編地址 54
5.5.1 標號 54
5.5.2 如何顯示十進製數字 58
5.5.3 在程序中聲明並初始化數據 58
5.5.4 分解數的各個數位 59
5.5.5 顯示分解齣來的各個數位 63
5.6 使程序進入無限循環狀態 64
5.7 完成並編譯主引導扇區代碼 66
5.7.1 主引導扇區有效標誌 66
5.7.2 代碼的保存和編譯 67
5.8 加載和運行主引導扇區代碼 67
5.8.1 把編譯後的指令寫入主引導扇區 67
5.8.2 啓動虛擬機觀察運行結果 68
5.9 程序的調試技術 68
5.9.1 開源的Bochs虛擬機軟件 68
5.9.2 Bochs下的程序調試入門 69
本章習題 75
第6章 相同的功能,不同的代碼 76
6.1 代碼清單6-1 76
6.2 跳過非指令的數據區 76
6.3 在數據聲明中使用字麵值 77
6.4 段地址的初始化 77
6.5 段之間的批量數據傳送 78
6.6 使用循環分解數位 80
6.7 計算機中的負數 81
6.7.1 無符號數和有符號數 81
6.7.2 處理器視角中的數據類型 85
6.8 數位的顯示 87
6.9 其他標誌位和條件轉移指令 88
6.9.1 奇偶標誌位PF 88
6.9.2 進位標誌CF 89
6.9.3 溢齣標誌OF 89
6.9.4 現有指令對標誌位的影響 90
6.9.5 條件轉移指令 90
6.10 NASM編譯器的$和$$標記 92
6.11 觀察運行結果 93
6.12 本章程序的調試 93
6.12.1 調試命令“n”的使用 93
6.12.2 調試命令“u”的使用 94
6.12.3 用調試命令“info”察看標誌位 96
本章習題 97
第7章 比高斯更快的計算 98
7.1 從1加到100的故事 98
7.2 代碼清單7-1 98
7.3 顯示字符串 98
7.4 計算1到100的纍加和 99
7.5 纍加和各個數位的分解與顯示 99
7.5.1 棧和棧段的初始化 99
7.5.2 分解各個數位並壓棧 101
7.5.3 齣棧並顯示各個數位 103
7.5.4 進一步認識棧 104
7.6 程序的編譯和運行 105
7.6.1 觀察程序的運行結果 105
7.6.2 在調試過程中察看棧中內容 106
7.7 8086處理器的尋址方式 107
7.7.1 寄存器尋址 107
7.7.2 立即尋址 107
7.7.3 內存尋址 108
本章習題 112
第8章 硬盤和顯卡的訪問與控製 113
8.1 本章代碼清單 114
8.2 用戶程序的結構 114
8.2.1 分段、段的匯編地址和段內匯編地址 114
8.2.2 用戶程序頭部 117
8.3 加載程序(器)的工作流程 120
8.3.1 初始化和決定加載位置 120
8.3.2 準備加載用戶程序 121
8.3.3 外圍設備及其接口 122
8.3.4 I/O端口和端口訪問 123
8.3.5 通過硬盤控製器端口讀扇區數據 125
8.3.6 過程調用 127
8.3.7 加載用戶程序 133
8.3.8 用戶程序重定位 134
8.3.9 將控製權交給用戶程序 137
8.3.10 8086處理器的無條件轉移指令 138
8.4 用戶程序的工作流程 140
8.4.1 初始化段寄存器和棧切換 140
8.4.2 調用字符串顯示例程 141
8.4.3 過程的嵌套 142
8.4.4 屏幕光標控製 142
8.4.5 取當前光標位置 143
8.4.6 處理迴車和換行字符 144
8.4.7 顯示可打印字符 145
8.4.8 滾動屏幕內容 145
8.4.9 重置光標 146
8.4.10 切換到另一個代碼段中執行 146
8.4.11 訪問另一個數據段 147
8.5 編譯和運行程序並觀察結果 147
本章習題 148
第9章 中斷和動態時鍾顯示 149
9.1 外部硬件中斷 149
9.1.1 非屏蔽中斷 150
9.1.2 可屏蔽中斷 150
9.1.3 實模式下的中斷嚮量錶 152
9.1.4 實時時鍾、CMOS RAM和BCD編碼 154
9.1.5 代碼清單9-1 157
9.1.6 初始化8259、RTC和中斷嚮量錶 157
9.1.7 使處理器進入低功耗狀態 159
9.1.8 實時時鍾中斷的處理過程 160
9.1.9 代碼清單9-1的編譯和運行 162
9.2 內部中斷 163
9.3 軟中斷 163
9.3.1 BIOS中斷 163
9.3.2 代碼清單9-2 165
9.3.3 從鍵盤讀字符並顯示 165
9.3.4 代碼清單9-2的編譯和運行 165
本章習題 166
第3部分 32位保護模式
第10章 32位x86處理器編程架構 169
10.1 IA-32架構的基本執行環境 169
10.1.1 寄存器的擴展 169
10.1.2 基本的工作模式 172
10.1.3 綫性地址 173
10.2 現代處理器的結構和特點 174
10.2.1 流水綫 174
10.2.2 高速緩存 175
10.2.3 亂序執行 175
10.2.4 寄存器重命名 176
10.2.5 分支目標預測 177
10.3 32位模式的指令係統 178
10.3.1 32位處理器的尋址方式 178
10.3.2 操作數大小的指令前綴 179
10.3.3 一般指令的擴展 181
本章習題 184
第11章 進入保護模式 185
11.1 代碼清單11-1 185
11.2 全局描述符錶 186
11.3 存儲器的段描述符 187
11.4 安裝存儲器的段描述符並加載GDTR 191
11.5 關於第21條地址綫A20的問題 193
11.6 保護模式下的內存訪問 195
11.7 清空流水綫並串行化處理器 199
11.8 保護模式下的棧 200
11.8.1 關於棧段描述符中的界限值 200
11.8.2 檢驗32位下的棧操作 201
11.9 程序的運行和調試 202
11.9.1 運行程序並觀察結果 202
11.9.2 處理器剛加電時的段寄存器狀態 203
11.9.3 設置PE位後的段寄存器狀態 205
11.9.4 JMP指令執行後的段寄存器狀態 205
11.9.5 察看全局描述符錶GDT 206
11.9.6 察看控製寄存器的內容 207
本章習題 207
第12章 存儲器的保護 208
12.1 代碼清單12-1 208
12.2 進入32位保護模式 208
12.2.1 話說mov ds,ax和mov ds,eax 208
12.2.2 創建GDT並安裝段描述符 209
12.3 修改段寄存器時的保護 211
12.4 地址變換時的保護 213
12.4.1 代碼段執行時的保護 213
12.4.2 棧操作時的保護 214
12.4.3 數據訪問時的保護 216
12.5 使用彆名訪問代碼段對字符排序 217
12.6 程序的編譯和運行 219
本章習題 220
第13章 程序的動態加載和執行 221
13.1 本章代碼清單 222
13.2 內核的結構、功能和加載 222
13.2.1 內核的結構 222
13.2.2 內核的加載 223
13.2.3 安裝內核的段描述符 225
13.3 在內核中執行 229
13.4 用戶程序的加載和重定位 230
13.4.1 用戶程序的結構 230
13.4.2 計算用戶程序占用的扇區數 232
13.4.3 簡單的動態內存分配 233
13.4.4 段的重定位和描述符的創建 234
13.4.5 重定位用戶程序內的符號地址 238
13.5 執行用戶程序 242
13.6 代碼的編譯、運行和調試 243
本章習題 244
第14章 任務和特權級保護 245
14.1 任務的隔離和特權級保護 246
14.1.1 任務、任務的LDT和TSS 246
14.1.2 全局空間和局部空間 248
14.1.3 特權級保護概述 250
14.2 代碼清單14-1 257
14.3 內核程序的初始化 257
14.3.1 調用門 258
14.3.2 調用門的安裝和測試 261
14.4 加載用戶程序並創建任務 264
14.4.1 任務控製塊和TCB鏈 264
14.4.2 使用棧傳遞過程參數 266
14.4.3 加載用戶程序 268
14.4.4 創建局部描述符錶 269
14.4.5 重定位U-SALT錶 270
14.4.6 創建0、1和2特權級的棧 271
14.4.7 安裝LDT描述符到GDT中 271
14.4.8 任務狀態段TSS的格式 272
14.4.9 創建任務狀態段TSS 276
14.4.10 安裝TSS描述符到GDT中 276
14.4.11 帶參數的過程返迴指令 277
14.5 用戶程序的執行 278
14.5.1 通過調用門轉移控製的完整過程 278
14.5.2 進入3特權級的用戶程序的執行 281
14.5.3 檢查調用者的請求特權級RPL 284
14.5.4 在Bochs中調試程序的新方法 286
本章習題 286
第15章 任務切換 287
15.1 本章代碼清單 287
15.2 任務切換前的設置 287
15.3 任務切換的方法 289
15.4 用call/jmp/iret指令發起任務切換的實例 292
15.5 處理器在實施任務切換時的操作 296
15.6 程序的編譯和運行 298
本章習題 299
第16章 分頁機製和動態頁麵分配 300
16.1 分頁機製概述 301
16.1.1 簡單的分頁模型 301
16.1.2 頁目錄、頁錶和頁 305
16.1.3 地址變換的具體過程 307
16.2 本章代碼清單 308
16.3 使內核在分頁機製下工作 309
16.3.1 創建內核的頁目錄錶和頁錶 309
16.3.2 任務全局空間和局部空間的頁麵映射 314
16.4 創建內核任務 319
16.4.1 內核的虛擬內存分配 319
16.4.2 頁麵位映射串和空閑頁的查找 320
16.4.3 創建頁錶並登記分配的頁 323
16.4.4 創建內核任務的TSS 324
16.5 用戶任務的創建和切換 325
16.5.1 多段模型和段頁式內存管理 325
16.5.2 平坦模型和用戶程序的結構 327
16.5.3 用戶任務的虛擬地址空間分配 328
16.5.4 用戶程序的加載 329
16.5.5 段描述符的創建(平坦模型) 332
16.5.6 重定位U-SALT並復製頁目錄錶 333
16.5.7 切換到用戶任務執行 334
16.6 程序的編譯、執行和調試 336
16.6.1 本章程序的編譯和運行方法 336
16.6.2 察看CR3寄存器的內容 337
16.6.3 察看綫性地址對應的物理頁信息 337
16.6.4 察看當前任務的頁錶信息 338
16.6.5 使用綫性(虛擬)地址調試程序 339
本章習題 339
第17章 中斷和異常的處理與搶占式多任務 340
17.1 中斷和異常 340
17.1.1 中斷和異常概述 340
17.1.2 中斷描述符錶、中斷門和陷阱門 343
17.1.3 中斷和異常處理程序的保護 345
17.1.4 中斷任務 347
17.1.5 錯誤代碼 348
17.2 本章代碼清單 349
17.3 內核的加載和初始化 349
17.3.1 徹底終結多段模型 349
17.3.2 創建中斷描述符錶 352
17.3.3 用定時中斷實施任務切換 354
17.3.4 8259A芯片的初始化 359
17.3.5 平坦模型下的字符串顯示例程 362
17.4 內核任務的創建 362
17.4.1 創建內核任務的TCB 362
17.4.2 宏匯編技術 364
17.5 用戶任務的創建 366
17.5.1 準備加載用戶程序 366
17.5.2 轉換後援緩衝器的刷新 367
17.5.3 用戶任務的創建和初始化 368
17.6 程序的編譯和執行 370
本章習題 371
附錄Ⅰ 本書用到的x86指令及其頁碼 372
附錄Ⅱ 本書用到的重要圖錶及其頁碼 374
· · · · · · (
收起)