Linux x64匯編語言編程 X64 Assembly Language Step-By-Step: Programming with Linux, 4/e

[美] 傑夫·鄧特曼(Jeff Duntemann)著 賈玉彬 王文傑 譯

  • Linux x64匯編語言編程-preview-1
  • Linux x64匯編語言編程-preview-2
  • Linux x64匯編語言編程-preview-3
Linux x64匯編語言編程-preview-1

買這商品的人也買了...

相關主題

商品描述

"《Linux x64匯編語言編程》介紹二進制、十六進制、計算、編程和x64架構的基礎知識,分析Linux軟件開發過程,講解NASM匯編器、x64指令集、內存尋址、過程、宏及Linux的C庫函數接口,披露軟件設計、編碼、測試和調試的實用技巧。本書示例代碼豐富,文筆幽默,將深奧的知識講得簡單易懂,引導你循序漸進地學會匯編編程。 《Linux x64匯編語言編程》是**的Intel/AMD x64教程,是學習x64匯編語言的黃金標準,非常適合自學。"

目錄大綱

目錄

 

第1章  一切都在計劃之中——真正理解電腦的工作原理   1

1.1  完美的周六計劃   1

1.1.1  步驟和測試   2

1.1.2  決定總是具有二元性   3

1.1.3  電腦像我們一樣思考   4

1.2  如果這是真的   4

1.3  將匯編語言編程比作方塊舞   4

1.4  將匯編語言編程比作棋盤游戲   5

1.4.1  代碼和數據   6

1.4.2  地址   7

1.4.3  總結   7

第2章  外星人基地——理解二進制和十六進制   9

2.1  新數學怪獸的回歸   9

2.1.1  使用火星文計數   10

2.1.2  剖析火星數字   12

2.1.3  數基的本質   13

2.2  八進制:鬼精靈如何偷走8和9   13

2.3  十六進制:解決數字短缺問題   17

2.4  從十六進制到十進制以及從十進制到十六進制   20

2.4.1  從十六進制到十進制   21

2.4.2  從十進制到十六進制   22

2.5  練習!練習!練習!   23

2.6  十六進制算術   24

2.6.1  列和進制   26

2.6.2  減法和借位   27

2.6.3  跨多列借位   28

2.6.4  重點是什麽?   29

2.7  二進制   29

2.7.1  二進制值   31

2.7.2  為什麽是二進制   33

2.8  十六進製作為二進制的簡寫   33

2.9  準備計算   35

第3章  揭開面紗——瞭解電腦的真實面貌   36

3.1  RAX寄存器,我們幾乎不瞭解   36

3.2  開關、晶體管和內存   38

3.2.1  如果敵方陸路來襲,則點亮一盞燈   38

3.2.2  晶體管開關   39

3.2.3  令人難以置信的比特縮小現象   41

3.2.4  隨機訪問   42

3.2.5  內存訪問時間   44

3.2.6  字節、字、雙字和四字   44

3.2.7  排成一排的精美芯片   45

3.3  CPU和裝配線   48

3.3.1  與內存對話   48

3.3.2  搭乘數據總線   49

3.3.3  寄存器   50

3.3.4  裝配線   51

3.4  遵循計劃的盒子   51

3.4.1  獲取並執行   52

3.4.2  CPU的內部結構   53

3.4.3  改變路線   55

3.5  什麽與如何:架構和微架構   56

3.5.1  不斷演變的架構   56

3.5.2  地下室的秘密機器   57

3.6  工廠經理   58

3.6.1  操作系統:轉角辦公室   59

3.6.2  BIOS:軟件不“軟”   59

3.6.3  多任務魔法   60

3.6.4  提升至內核   61

3.6.5  內核爆炸   62

3.6.6  計劃   63

第4章  尋址、尋址、尋址——寄存器、內存尋址及瞭解數據的位置   64

4.1  內存模型的樂趣   64

4.1.1  16位能“買到”64KB   65

4.1.2  兆字節(MB)的本質   68

4.1.3  向後兼容和虛擬86模式   69

4.1.4  16位的視野限制   70

4.2  分段的本質   71

4.2.1  一條地平線,而不是一個具體位置   74

4.2.2  使用16位寄存器生成20位地址   74

4.3  分段寄存器   76

4.3.1  分段寄存器和x64   77

4.3.2  通用寄存器   77

4.3.3  寄存器的高位和低位   79

4.3.4  指令指針   81

4.3.5  標志寄存器   82

4.3.6  數學協處理器及其寄存器   82

4.4  四種主要的匯編編程模型   83

4.4.1  實模式平面模型   83

4.4.2  實模式分段模型   85

4.4.3  32位保護模式平面模型   87

4.4.4  64位長模式編程模型   89

第5章  匯編的正確方式——匯編語言程序的開發過程   91

5.1  編程的96種方法   91

5.2  文件及其內容   92

5.2.1  二進制文件與文本文件   92

5.2.2  使用GHex十六進制編輯器查看二進制文件內部   94

5.2.3  解釋原始數據   97

5.2.4  字節順序   98

5.3  輸入文本,輸出代碼   102

5.3.1  匯編語言   102

5.3.2  註釋   104

5.3.3  當心“只寫源代碼”!   105

5.3.4  目標代碼、鏈接器和庫   106

5.3.5  可重定位性   108

5.4  匯編語言的開發過程   108

5.4.1  工作目錄的規則   110

5.4.2  編輯源代碼文件   110

5.4.3  匯編源代碼文件   111

5.4.4  匯編器錯誤   111

5.4.5  回到編輯器   113

5.4.6  編譯器警告   113

5.5  鏈接目標代碼文件   114

5.5.1  鏈接器錯誤   115

5.5.2  測試EXE文件   115

5.5.3  錯誤與缺陷   116

5.5.4  調試器和調試   117

5.6  走進匯編語言的世界   117

5.6.1  安裝軟件   118

5.6.2  步驟1:在編輯器中編輯程序   120

5.6.3  步驟2:使用NASM匯編程序   121

5.6.4  步驟3:使用ld鏈接程序   123

5.6.5  步驟4:測試可執行文件   124

5.6.6  步驟5:在調試器中觀察它的運行   124

第6章  一個可使用工具的立足之地——Linux和塑造你的工作方式的工具   126

6.1  集成開發環境(IDE)   126

6.2  SASM簡介   128

6.2.1  配置SASM   129

6.2.2  SASM的字體   130

6.2.3  使用編譯器鏈接   130

6.2.4  SASM速覽   132

6.2.5  SASM的編輯器   134

6.2.6  SASM對你的代碼有何要求   134

6.3  Linux和終端   135

6.3.1  Linux控制台   136

6.3.2  Konsole中的字符編碼   136

6.3.3  三個標準UNIX文件   138

6.3.4  I/O重定向   139

6.3.5  簡單文本過濾器   141

6.3.6  使用SASM內部的標準輸入和標準輸出   142

6.3.7  使用轉義序列進行終端控制   142

6.3.8  為什麽不使用GUI應用程序   143

6.4  使用Linux Make   145

6.4.1  依賴   145

6.4.2  當文件是最新的   147

6.4.3  依賴鏈   148

6.4.4  調用Make   149

6.4.5  為Make創建自定義按鍵綁定   150

6.4.6  使用touch強制構建   151

6.5  使用SASM進行調試   152

第7章  遵循你的指令——近距離觀察機器指令   154

7.1  構建自己的沙箱   154

7.2  指令及其操作數   157

7.3  源操作數和目標操作數   157

7.3.1  即時數據   158

7.3.2  寄存器數據   160

7.3.3  內存數據和有效地址   162

7.3.4  混淆數據及其地址   162

7.3.5  內存數據的大小   163

7.3.6  糟糕的舊時光   164

7.4  團結在“標志”周圍   164

7.4.1  標志禮儀   167

7.4.2  在SASM中觀察標志   167

7.4.3  使用INC和DEC進行加1和減1操作   167

7.4.4  標志如何改變程序的執行   169

7.4.5  如何檢查SASM中的變量   170

7.5  有符號值和無符號值   172

7.5.1  二進制補碼和NEG   172

7.5.2  符號擴展和MOVSX   174

7.6  隱式操作數和MUL   176

7.6.1  MUL和進制標志   177

7.6.2  使用DIV進行無符號除法   178

7.6.3  MUL和DIV速度很慢   179

7.7  閱讀和使用匯編語言參考   180

7.7.1  復雜記憶的備忘錄   180

7.7.2  初學者的匯編語言參考   181

7.7.3  標志   181

7.8  NEG取反(二進制補碼,即乘以-1)   182

7.8.1  受影響的標志   182

7.8.2  有效形式   182

7.8.3  示例   182

7.8.4  備註   182

7.8.5  有效形式   183

7.8.6  操作數符號   183

7.8.7  示例   184

7.8.8  備註   184

7.8.9  這里沒有提到的內容……   185

第8章  我們崇高的目標——創建有效的程序   186

8.1  匯編語言程序的骨架   186

8.1.1  初始註釋塊   188

8.1.2  .data部分   188

8.1.3  .bss部分   189

8.1.4  .text部分   189

8.1.5  標簽   190

8.1.6  初始化數據的變量   191

8.1.7  字符串變量   191

8.1.8  使用EQU和$推導字符串長度   193

8.2  通過棧後進先出   194

8.2.1  每小時500個盤子   195

8.2.2  倒置堆疊   196

8.2.3  壓入指令   197

8.2.4  POP指令登場   198

8.2.5  PUSHA和POPA已停用   199

8.2.6  壓入和彈出的詳細信息   200

8.2.7  短期存儲   201

8.3  通過SYSCALL使用Linux內核服務   202

8.3.1  通過SYSCALL指令使用x64內核服務   202

8.3.2  ABI與API的區別   203

8.3.3  ABI的寄存器參數方案   203

8.3.4  通過SYSCALL退出程序   204

8.3.5  被SYSCALL破壞的寄存器   205

8.4  設計一個不平凡的程序   205

8.4.1  定義問題   206

8.4.2  從偽代碼開始   207

8.4.3  持續改進   207

8.4.4  那些不可避免的驚訝時刻   211

8.4.5  掃描緩沖區   212

8.4.6  差一錯誤   214

8.4.7  從偽代碼到匯編代碼   215

8.4.8  SASM輸出窗口的陷阱   218

8.4.9  進一步學習   218

第9章  位、標志、分支和表——逐步駛入匯編編程的主航道   219

9.1  位就是位(字節也是位)   219

9.1.1  位編號   220

9.1.2  最合乎邏輯的做法   220

9.1.3  AND指令   221

9.1.4  掩碼位   221

9.1.5  OR指令   223

9.1.6  XOR(異或)指令   223

9.1.7  NOT指令   224

9.1.8  分段寄存器沒有邏輯   225

9.2  移位   225

9.2.1  通過什麽移位   226

9.2.2  移位的工作原理   226

9.2.3  將位放入進制標志   227

9.2.4  旋轉指令   227

9.2.5  通過進制標志旋轉位   228

9.2.6  將已知值設置到進制標志中   228

9.3  位操作實戰   229

9.3.1  將一字節拆分成兩個“半字節”   232

9.3.2  將高半字節移入低半字節   232

9.3.3  使用查找表   233

9.3.4  通過移位和加法進行乘法   234

9.4  標志、測試和分支   237

9.4.1  無條件跳轉   237

9.4.2  有條件跳轉   238

9.4.3  在缺少條件的情況下跳轉   239

9.4.4  標志   240

9.4.5  使用CMP進行比較   240

9.4.6  跳轉指令的“叢林”   241

9.4.7  “大於”與“高於”   241

9.4.8  使用TEST查找1位   243

9.4.9  使用BT尋找0位   244

9.5  x64長模式內存尋址詳解   244

9.5.1  有效地址計算   246

9.5.2  位移   247

9.5.3  x64位移大小問題   247

9.5.4  基址尋址   248

9.5.5  基址 + 位移尋址   248

9.5.6  基址 + 索引尋址   248

9.5.7  索引×比例+位移尋址   249

9.5.8  其他尋址方案   251

9.5.9  LEA:絕密數學機器   253

9.6  字符表轉換   254

9.6.1  轉換表   254

9.6.2  使用MOV或XLAT進行轉換   256

9.7  用表代替計算   261

第10章  分而治之——使用過程和宏來應對程序復雜性   262

10.1  層層嵌套   263

10.2  調用和返回   272

10.2.1  調用中的調用   274

10.2.2  意外遞歸的危險   275

10.2.3  需要警惕的標志相關錯誤   276

10.2.4  過程及其所需的數據   278

10.2.5  保存調用者的寄存器   278

10.2.6  在Linux系統調用中保存寄存器   280

10.2.7  PUSHAD和POPAD已廢棄   281

10.2.8  本地數據   283

10.2.9  在過程定義中放置常量數據   283

10.2.10  更多表技巧   285

10.3  本地標簽和跳轉的長度   287

10.3.1  強制本地標簽訪問   290

10.3.2  短、近和遠跳轉   290

10.4  構建外部過程庫   291

10.4.1  當工具達到極限時   292

10.4.2  在SASM中使用包含文件   292

10.4.3  SASM包含文件的存儲位置   299

10.4.4  創建包含文件庫的最佳方法   300

10.4.5  獨立匯編和模塊   301

10.4.6  全局和外部聲明   301

10.4.7  全局變量和外部變量的機制   303

10.4.8  將庫鏈接到程序中   313

10.4.9  太多過程和庫會造成危險   313

10.5  製作過程的藝術   314

10.5.1  可維護性和重用性   314

10.5.2  決定什麽應該是一個過程   315

10.5.3  使用註釋標題   316

10.6  Linux控制臺中的簡單光標控制   317

10.7  創建和使用宏   325

10.7.1  宏定義的機制   326

10.7.2  定義帶參數的宏   332

10.7.3  調用宏的機制   333

10.7.4  宏內的本地標簽   334

10.7.5  宏庫作為包含文件   335

10.7.6  宏與過程:優點和缺點   335

第11章  字符串及其他——那些令人驚嘆的字符串指令   337

11.1  匯編語言字符串的概念   338

11.1.1  徹底改變你的“字符串感”   338

11.1.2  源字符串和目標字符串   339

11.1.3  文本顯示虛擬屏幕   339

11.2  REP STOSB:軟件機關槍   347

11.2.1  機關槍式操作虛擬顯示   348

11.2.2  執行STOSB指令   348

11.2.3  STOSB和方向標志DF   349

11.2.4  定義顯示緩沖區中的行   350

11.2.5  將緩沖區發送到Linux控制台   351

11.3  半自動武器:沒有REP的STOSB   351

11.3.1  誰減少了RCX?   352

11.3.2  LOOP指令   352

11.3.3  在屏幕上顯示標尺   353

11.3.4  MUL不是IMUL   354

11.3.5  Ruler的教訓   355

11.3.6  STOS的四種大小   355

11.3.7  再見,BCD算術   356

11.4  MOVSB:快速塊復制   356

11.4.1  DF和重疊阻擋移動   357

11.4.2  單步REP字符串指令   360

11.5  將數據存儲到不連續的字符串中   361

11.5.1  顯示一個ASCII表   361

11.5.2  嵌套指令循環   366

11.5.3  當RCX變為0時跳轉   367

11.5.4  關閉內循環   367

11.5.5  關閉外循環   368

11.5.6  回顧showchar   369

11.6  命令行參數、字符串搜索和Linux棧   369

11.6.1  顯示SASM的命令行參數   370

11.6.2  使用SCASB進行字符串搜索   373

11.6.3  REPNE與REPE   374

11.6.4  無法將命令行參數傳遞給SASM中的程序   375

11.7  棧及其結構和使用方法   375

11.7.1  直接訪問棧   377

11.7.2  程序序言和結語   380

11.7.3  棧上的尋址數據   381

11.7.4  不要彈出   382

第12章  轉向C——調用C語言編寫的外部函數   383

12.1  GNU   384

12.1.1  瑞士軍刀編譯器   385

12.1.2  以GNU方式構建代碼   385

12.1.3  SASM使用GCC   387

12.1.4  如何在匯編工作中使用gcc   387

12.1.5  為什麽不使用gas   388

12.2  鏈接標準C庫   389

12.2.1  C調用約定   390

12.2.2  調用者、被調用者和破壞者   390

12.2.3  設置棧幀   392

12.2.4  在結語中銷毀棧幀   393

12.2.5  棧對齊   393

12.2.6  通過puts()輸出字符   395

12.3  使用printf()格式化文本輸出   397

12.3.1  將參數傳遞給printf()   398

12.3.2  printf()需要在RAX中加上前置0   399

12.3.3  你需要使用-no-pie選項   400

12.4  使用fgets()和scanf()輸入數據   400

12.5  成為Linux時間領主   406

12.5.1  C庫的時間機器   406

12.5.2  從系統時鐘獲取time_t值   407

12.5.3  將time_t值轉換為格式化字符串   408

12.5.4  生成單獨的本地時間值   409

12.5.5  使用MOVSD復制glibc的tm結構   409

12.6  理解AT&T指令助記符   413

12.6.1  AT&T助記符約定   413

12.6.2  AT&T內存引用語法   415

12.7  生成隨機數   416

12.7.1  使用srand()為生成器設定種子   416

12.7.2  生成偽隨機數   417

12.7.3  相比之下有些比特更隨機   423

12.7.4  調用寄存器中的地址   425

12.7.5  使用puts()將一個裸換行符發送到控制台   426

12.7.6  如何向libc函數傳遞六個以上的參數   426

12.8  C語言如何處理命令行參數   427

12.9  簡單文件 I/O   430

12.9.1  使用sscanf()將字符串轉換為數字   431

12.9.2  創建和打開文件   432

12.9.3  使用fgets()從文件讀取文本   434

12.9.4  使用fprintf()將文本寫入文件   436

12.9.5  將過程收集到庫中的註意事項   437

12.10  永遠學習,永遠不要停下來   444

12.10.1  何去何從   445

12.10.2  走出原點   446

 

(以下內容可掃描封底二維碼下載)

附錄A  Insight調試器的回歸   447

附錄B  部分x64指令參考   454

附錄C  字符集圖表   509