目錄
第1章 又一個令人愉快的星期六 1
1.1 一切盡在計劃之中 1
1.1.1 步驟和測試 2
1.1.2 不止兩種方式 3
1.1.3 計算機像我們一樣思考 4
1.2 如果這是真實情況 4
1.3 此路不通,請繞行 5
1.3.1 Big Bux遊戲 6
1.3.2 玩Big Bux遊戲 8
1.4 像棋盤遊戲一樣的匯編語言編程 9
1.4.1 代碼和數據 10
1.4.2 地址 11
1.4.3 隱喻,將軍 12
第2章 外星基數 14
2.1 新數學怪物歸來 14
2.2 在火星上計數 15
2.2.1 火星數字剖析 17
2.2.2 數字基數的本質 19
2.3 八進製:綠色精怪怎樣偷走8和9的 19
2.4 十六進製:解決數字的短缺 23
2.5 從十六進製到十進製,從十進製到十六進製 27
2.5.1 從十六進製到十進製 27
2.5.2 從十進製到十六進製 28
2.5.3 練習!練習!再練習 30
2.6 十六進製運算 31
2.6.1 列和進位 34
2.6.2 減法和藉位 34
2.6.3 跨多列藉位 36
2.6.4 意義何在 37
2.7 二進製 37
2.7.1 二進製值 39
2.7.2 為什麼使用二進製 41
2.8 二進製簡寫方式:十六進製 42
第3章 摘下麵具 44
3.1 RAXie,我們怎麼不認識你 44
3.2 開關、晶體管和存儲器 46
3.2.1 如果走陸路,就是1 47
3.2.2 晶體管開關 47
3.2.3 難以置信的位縮水 49
3.2.4 隨機訪問 51
3.2.5 存儲器訪問時間 52
3.2.6 字節,字,雙字,四字 53
3.2.7 精緻的芯片排成一行 54
3.2.8 車間工長和流水綫 57
3.2.9 對話內存 57
3.2.10 駕馭數據總綫 58
3.2.11 車間工長的口袋 59
3.2.12 流水綫 60
3.3 遵循計劃行事的盒子 60
3.3.1 取指和執行 61
3.3.2 車間工長的內髒 62
3.3.3 改變航嚮 64
3.4 是什麼vs.怎麼做:體係結構和微體係結構 65
3.4.1 體係結構的演變 66
3.4.2 地下室裏的秘密機製 67
3.5 工廠經理 68
3.5.1 操作係統:角落辦公室 69
3.5.2 BIOS:是軟件,但並不軟 69
3.5.3 多任務魔術 70
3.5.4 內核提升 71
3.5.5 內核爆炸 73
3.5.6 計劃 73
第4章 位置,位置,位置 74
4.1 內存模式的樂趣 74
4.1.1 16 位將帶來64K存儲空間 75
4.1.2 兆字節的本質 79
4.1.3 嚮後兼容和虛擬86模式 80
4.1.4 16位眼罩 80
4.2 段的本質 81
4.2.1 一個界限,而非一個位置 84
4.2.2 用兩個16位寄存器構成20位地址 84
4.3 16位和32位寄存器 87
4.3.1 通用寄存器 88
4.3.2 半寄存器 90
4.3.3 指令指針寄存器 91
4.3.4 標誌寄存器 92
4.4 三種主要的匯編編程模型 93
4.4.1 實模式平麵模型 93
4.4.2 實模式段模型 95
4.4.3 保護模式平麵模型 97
4.5 保護模式下不再允許我們做的事情 100
4.5.1 內存映射視頻係統 100
4.5.2 直接訪問端口硬件 101
4.5.3 直接調用BIOS 102
4.6 展望未來:64位“長模式” 102
第5章 匯編的權利 105
5.1 文件及其包含的內容 106
5.1.1 二進製文件 vs. 文本文件 106
5.1.2 用 Bless 編輯器查看文件內容 108
5.1.3 解釋原始數據 112
5.1.4 “字節序” 113
5.2 文本進去, 代碼齣來 116
5.2.1 匯編語言 117
5.2.2 注釋 119
5.2.3 當心“隻寫”源代碼 120
5.2.4 目標代碼和連接器 120
5.2.5 重定位能力 123
5.3 匯編語言開發過程 124
5.3.1 工作目錄規範 125
5.3.2 編輯源代碼文件 126
5.3.3 編譯源代碼文件 126
5.3.4 匯編錯誤 127
5.3.5 迴到編輯器 129
5.3.6 匯編警告 129
5.3.7 連接目標代碼文件 130
5.3.8 連接錯誤 131
5.3.9 測試.EXE文件 131
5.3.10 錯誤vs.漏洞 132
5.3.11 我們還在那裏嗎 133
5.3.12 調試器和調試 133
5.4 沿著匯編小路旅行 134
5.4.1 安裝軟件 135
5.4.2 第1步:在編輯器中編輯程序 137
5.4.3 第2步:使用NASM編譯程序 138
5.4.4 第3步:使用LD連接器 140
5.4.5 第4步:測試可執行文件 141
5.4.6 第5步:在調試器中觀察程序運行 142
5.4.7 準備好要來真格的瞭嗎 148
第6章 有地兒,有工具 149
6.1 Kate 編輯器 151
6.1.1 安裝Kate編輯器 151
6.1.2 啓動Kate 152
6.1.3 配置 154
6.1.4 Kate 會話 156
6.1.5 Kate編輯器的文件管理 158
6.1.6 嚮工具欄添加菜單項 161
6.1.7 Kate編輯器的編輯控製 162
6.1.8 編程期間使用Kate編輯器 166
6.2 Linux 和終端 169
6.2.1 Linux 控製颱 169
6.2.2 Konsole中的字符編碼 170
6.2.3 三個標準Unix文件 172
6.2.4 I/O 重定嚮 173
6.2.5 簡易文本過濾器 175
6.2.6 使用轉義序列進行終端控製 177
6.2.7 為什麼不用匯編語言編寫GUI應用程序呢 178
6.3 使用Linux Make 179
6.3.1 依賴條件 180
6.3.2 文件何時最新 182
6.3.3 依賴鏈 182
6.3.4 從Kate編輯器內部調用Make實用工具 184
6.3.5 使用touch命令強製執行生成操作 187
6.4 Insight 調試器 187
6.4.1 運行Insight 188
6.4.2 Insight的眾多窗口 189
6.4.3 快速體驗Insight 190
6.4.4 拿起你的工具 193
第7章 跟蹤指令 194
7.1 為自己建立一個沙盒 194
7.1.1 一個最小的NASM程序 195
7.1.2 指令及其操作數 197
7.1.3 源操作數和目標操作數 197
7.1.4 立即數 198
7.1.5 寄存器數據 200
7.1.6 內存數據 202
7.1.7 混淆數據和它的地址 203
7.1.8 內存數據的尺寸 204
7.1.9 糟糕的過去 204
7.2 CPU的標誌位 205
7.2.1 標誌規範 208
7.2.2 使用INC指令和DEC指令加1和減1 208
7.2.3 從Insight中觀察標誌 209
7.2.4 標誌如何改變程序的執行 211
7.3 有符號值和無符號值 214
7.3.1 補碼和NEG 214
7.3.2 符號擴展和MOVSX 217
7.4 隱式操作數和Mul 219
7.4.1 MUL 和進位標誌 221
7.4.2 使用DIV實現無符號除法 221
7.4.3 x86中的“慢動作”指令 223
7.5 閱讀和使用匯編語言參考資料 223
7.5.1 對於復雜記憶的喚醒文件 224
7.5.2 初學者匯編語言參考指南 224
7.5.3 標誌 225
7.6 NEG:求補(求補碼;即,與-1相乘) 225
7.6.1 閤法形式 227
7.6.2 操作數符號 227
7.6.3 示例 228
7.6.4 注解 228
7.6.5 這裏沒有包含的內容 229
第8章 我們的崇高目標 230
8.1 匯編語言程序的基本框架 230
8.1.1 最開始處的注釋塊 232
8.1.2 .data段 233
8.1.3 .bss?段 233
8.1.4 .text段 234
8.1.5 標號 234
8.1.6 已初始化變量 235
8.1.7 字符串變量 235
8.1.8 通過EQU和$推導字符串的長度 237
8.2 通過堆棧實現後進先齣 239
8.2.1 每小時500個盤子 239
8.2.2 堆棧的內容上下顛倒 241
8.2.3 Push-y指令 242
8.2.4 POP 指令 244
8.2.5 臨時存儲 246
8.3 通過INT80使用Linux內核服務 247
8.3.1 不中斷任何事情的中斷 247
8.3.2 再次返迴 252
8.3.3 通過使用 INT 80h退齣一個程序 253
8.3.4 軟件中斷VS硬件中斷 254
8.3.5 INT 80h和可移植性盲目崇拜 255
8.4 設計一個有價值的程序 256
8.4.1 問題定義 257
8.4.2 從僞代碼開始 258
8.4.3 連續改進 259
8.4.4 不可避免的“哎呀!”時刻 263
8.4.5 掃描緩衝區 264
8.4.6 緩衝溢齣(“Off By One”) 錯誤 266
8.4.7 進一步學習 271
第9章 位、標誌、分支和錶 272
9.1 位就是二進製位(字節也是二進製位) 272
9.1.1 位編號 273
9.1.2 邏輯操作 273
9.1.3 與指令 274
9.1.4 位屏蔽 275
9.1.5 或指令 276
9.1.6 異或指令 276
9.1.7 非指令 278
9.1.8 段寄存器對邏輯操作沒有反應 278
9.2 移位操作 279
9.2.1 根據什麼進行移位操作 279
9.2.2 移位指令的工作原理 279
9.2.3 將位移入進位標誌 280
9.2.4 循環移位指令 280
9.2.5 將已知值存入進位標誌CF 282
9.3 位操作 282
9.3.1 將一個字節分解為兩個“半字節” 285
9.3.2 將高半字節移入低半字節 286
9.3.3 使用查找錶 286
9.3.4 通過移位和相加來實現相乘 288
9.4 標誌、測試和分支 291
9.4.1 無條件轉移 292
9.4.2 條件轉移指令 292
9.4.3 條件“缺席”時進行跳轉 293
9.4.4 標誌 294
9.4.5 通過CMP進行比較操作 295
9.4.6 轉移指令的錯綜復雜之處 296
9.4.7 “大於”與“以上” 296
9.4.8 使用TEST指令查找位1 298
9.4.9 使用BT指令查找位0 300
9.5 保護模式下內存尋址詳解 301
9.5.1 有效地址計算 303
9.5.2 位移量 303
9.5.3 基址+位移量尋址方式 304
9.5.4 基址+索引尋址方式 304
9.5.5 索引×縮放比例+位移量尋址方式 305
9.5.6 其他尋址方式 307
9.5.7 LEA:最機密的數學機器 309
9.5.8 16位寄存器的負擔 311
9.6 字符錶轉換 312
9.6.1 轉換錶 312
9.6.2 用MOV或者XLAT進行轉換 315
9.7 用錶來代替計算 319
第10章 分治 321
10.1 盒子裏麵的盒子 322
10.2 調用和返迴 331
10.2.1 調用中的調用 334
10.2.2 意外遞歸的危險 335
10.2.3 一個需要提防的標誌規範Bug 336
10.2.4 過程及其所需的數據 337
10.2.5 保存主調程序的寄存器 338
10.2.6 局部數據 341
10.2.7 更多的錶格技巧 342
10.2.8 在過程定義中加入常量數據 344
10.3 局部標號和跳轉的長度 345
10.3.1 “強行”訪問局部標號 348
10.3.2 短轉移、近轉移和遠轉移 349
10.4 生成外部過程庫 350
10.4.1 全局聲明和外部聲明 351
10.4.2 全局過程和外部過程的機製 353
10.4.3 連接庫文件到程序中 361
10.4.4 太多過程和太多庫的危險 362
10.5 自定義過程的藝術 362
10.5.1 可維護性和可重用性 363
10.5.2 確定哪些代碼應該成為一個過程 364
10.5.3 使用注釋標頭 365
10.6 Linux控製颱下的簡單光標控製 366
10.7 創建和使用宏 374
10.7.1 宏定義機製 375
10.7.2 定義帶參數的宏 380
10.7.3 宏調用機製 382
10.7.4 宏內部的局部標號 383
10.7.5 像包含文件一樣的宏庫文件 384
10.7.6 宏?vs.?過程:優點和缺點 385
第11章 字符串奏鳴麯 387
11.1 匯編語言字符串的概念 387
11.1.1 徹底顛覆你的“字符串感覺” 388
11.1.2 源字符串和目標 字符串 388
11.1.3 虛擬文本顯示屏 389
11.2 REP STOSB,軟件機槍 397
11.2.1 機槍掃射虛擬顯示器 397
11.2.2 執行STOSB 指令 398
11.2.3 STOSB 和方嚮標誌(DF) 399
11.2.4 在顯示緩衝區中定義行 400
11.2.5 將緩衝區發送到Linux控製颱 401
11.3 半自動武器:不帶REP的STOSB 401
11.3.1 是誰遞減瞭ECX 402
11.3.2 LOOP指令 402
11.3.3 在屏幕上顯示一個標尺 403
11.3.4 MUL並非 IMUL 404
11.3.5 添加ASCII數字 406
11.3.6 調整AAA 408
11.3.7 Ruler過程的教訓 409
11.3.8 STOS指令的16位版本和32位版本 409
11.4 MOVSB:快速塊拷貝 409
11.4.1 DF和重疊塊移動 411
11.4.2 使用Insight單步調試REP字符串指令 413
11.5 將數據存儲到不連續的字符串中 414
11.5.1 顯示一個ASCII錶 414
11.5.2 嵌套指令循環 416
11.5.3 當ECX變為0時進行跳轉 416
11.5.4 關閉內層循環 417
11.5.5 關閉外層循環 418
11.5.6 Showchar小結 419
11.6 命令行參數和堆棧檢查 419
11.6.1 兩塊虛擬內存 420
11.6.2 Linux堆棧剖析 422
11.6.3 為什麼堆棧的地址是不可預測的 424
11.6.4 使用Insight設置命令行參數 424
11.6.5 通過Insight的內存視圖查看堆棧 425
11.7 使用SCASB進行字符串搜索 427
11.7.1 REPNE v.s. REPE 431
11.7.2 從堆棧中彈齣,還是對堆棧尋址 432
11.7.3 額外的學分 434
第12章 C語言 435
12.1 什麼是GNU 436
12.1.1 “瑞士軍刀” 編譯器 437
12.1.2 以GNU的方式生成代碼 437
12.1.3 如何在匯編工作中使用gcc 439
12.1.4 為什麼不用gas 440
12.2 連接到標準的C函數庫 441
12.2.1 C調用公約 442
12.2.2 建立一個框架 443
12.2.3 保存和恢復寄存器 443
12.2.4 建立堆棧幀 444
12.2.5 銷毀堆棧幀 446
12.2.6 通過puts()輸齣字符 447
12.3 使用printf()格式化文本輸齣 448
12.4 使用fgets()和scanf()進行數據輸入 452
12.5 駕馭時間 459
12.5.1 C庫的時間機製 459
12.5.2 從係統時鍾中取齣time_t值 461
12.5.3 將time_t 值轉換為一個格式化字符串 461
12.5.4 生成單獨的本地時間值 462
12.5.5 通過使用MOVSD復製glibc的tm結構 463
12.6 理解 AT&T 指令助記符 467
12.6.1 AT&T助記符公約 467
12.6.2 查看gcc創建的gas源文件 468
12.6.3 AT&T 內存引用語法 471
12.7 産生隨機數 472
12.7.1 利用srand()為隨機生成器“播種” 473
12.7.2 産生僞隨機數 474
12.7.3 有些位比其他位更具隨機性 479
12.7.4 調用寄存器中的地址 481
12.8 C如何看待命令行參數 482
12.9 簡單文件輸入/輸齣 484
12.9.1 通過sscanf()將字符串轉換為數字 485
12.9.2 創建和打開文件 486
12.9.3 使用fgets()從文件中讀取文本 488
12.9.4 使用fprintf()寫文本到文件中 490
12.9.5 關於收集過程到庫中的注解 492
結論:不是結束,而是剛剛開始 501
附錄A 部分x86指令集 505
附錄B 字符集圖 565
· · · · · · (
收起)