64位汇编语言的编程艺术 / 计算机科学丛书
定价:¥199.00
作者: [美]兰德尔·海德
出版时间:2024-01-16
出版社:机械工业出版社
- 机械工业出版社
- 9787111741268
- 1-2
- 578728
- 平装
- 2024-01-16
- 1182
内容简介
本书源于作者的经典书籍The Art of Assembly Language,从32位汇编语言升级为64位汇编语言,基于Microsoft宏汇编程序(MASM)讲解x86-64 CPU上汇编语言的编程艺术。本书从计算机的组成结构开始介绍,包括计算机数据表示和运算,以及内存的访问和组织等。之后详细讲解汇编语言程序设计,涉及过程和算术运算的相关知识,再通过低级控制结构过渡到高级主题,如表查找和位操作。此外,还探索了x87浮点单元、SIMD指令,以及MASM的宏工具。书中的程序清单均可免费下载,供读者即学即用。本书适合计算机专业的学生、相关领域的从业人员以及对汇编语言感兴趣的技术人员阅读。
目录
目 录
The Art of 64-Bit Assembly: x86-64 Machine Organization and Programming
译者序
推荐序
前言
致谢
第一部分 计算机的组成结构
第1章 汇编语言的第一个程序 2
1.1 先决条件 2
1.2 在计算机上安装MASM 3
1.3 在计算机上安装文本编辑器 3
1.4 MASM程序的结构剖析 3
1.5 运行第一个MASM程序 4
1.6 运行第一个MASM和C++的混合
程序 4
1.7 英特尔x86-64 CPU系列简介 6
1.8 内存子系统 9
1.9 在MASM中声明内存变量 10
1.9.1 将内存地址与变量关联 11
1.9.2 将数据类型与变量关联 12
1.10 在MASM中声明(命名)常量 12
1.11 基本的机器指令 13
1.11.1 mov指令 13
1.11.2 指令操作数的类型检查 14
1.11.3 add和sub指令 15
1.11.4 lea指令 15
1.11.5 call和ret指令以及MASM
过程 16
1.12 调用C/C++过程 17
1.13 “Hello, world!”程序 18
1.14 在汇编语言中返回函数结果 19
1.15 自动化构建过程 24
1.16 微软ABI注释 25
1.16.1 变量大小 25
1.16.2 寄存器的用途 28
1.16.3 栈对齐 28
1.17 拓展阅读资料 28
1.18 自测题 29
第2章 计算机数据表示和运算 31
2.1 数制系统 31
2.1.1 十进制数制系统的回顾 31
2.1.2 二进制数制系统 32
2.1.3 二进制约定 32
2.2 十六进制数制系统 33
2.3 关于数字与表示的注释 34
2.4 数据组织 36
2.4.1 位 36
2.4.2 半字节 36
2.4.3 字节 37
2.4.4 字 38
2.4.5 双字 39
2.4.6 四字和八字 39
2.5 位的逻辑运算 39
2.5.1 逻辑与运算 40
2.5.2 逻辑或运算 40
2.5.3 逻辑异或运算 40
2.5.4 逻辑非运算 41
2.6 二进制数和位串的逻辑运算 41
2.7 有符号数和无符号数 45
2.8 符号扩展和零扩展 49
2.9 符号缩减和饱和法 49
2.10 简要回顾:控制转移指令概述 50
2.10.1 jmp指令 50
2.10.2 条件跳转指令 51
2.10.3 cmp指令和相应的条件
跳转 52
2.10.4 条件跳转的同义词 53
2.11 移位和循环移位 54
2.12 位字段和打包数据 57
2.13 IEEE浮点数格式 63
2.13.1 单精度格式 64
2.13.2 双精度格式 65
2.13.3 扩展精度格式 65
2.13.4 规范化浮点值 65
2.13.5 非数值数据 66
2.13.6 MASM对浮点值的支持 66
2.14 BCD表示法 67
2.15 字符 67
2.15.1 ASCII字符编码 68
2.15.2 MASM对ASCII字符的
支持 69
2.16 Unicode字符集 70
2.16.1 Unicode码位 70
2.16.2 Unicode码平面 70
2.16.3 Unicode编码 71
2.17 MASM对Unicode的支持 72
2.18 拓展阅读资料 72
2.19 自测题 72
第3章 内存的访问和组织 76
3.1 运行时的内存组织 76
3.1.1 “.code”段 77
3.1.2 “.data”段 77
3.1.3 “.const”段 78
3.1.4 “.data?”段 79
3.1.5 程序中声明段的组织方式 79
3.1.6 内存访问和4KB内存管理
单元页 80
3.2 MASM如何为变量分配内存 81
3.3 标签声明 82
3.4 小端模式和大端模式的数据组织
方式 82
3.5 内存访问 84
3.6 MASM对数据对齐的支持 85
3.7 x86-64的寻址模式 87
3.7.1 x86-64的寄存器寻址模式 88
3.7.2 x86-64的64位内存寻址模式 88
3.7.3 不支持大地址的应用程序 91
3.8 地址表达式 94
3.9 栈段以及push和pop指令 97
3.9.1 基本的push指令 97
3.9.2 基本的pop指令 98
3.9.3 使用push和pop指令保存
寄存器的状态 99
3.10 栈 99
3.11 其他push和pop指令 102
3.12 不通过弹出栈从栈中移除数据 102
3.13 不通过弹出栈访问压入栈的
数据 103
3.14 微软ABI注释 104
3.15 拓展阅读资料 104
3.16 自测题 104
第4章 常量、变量和数据类型 106
4.1 imul指令 106
4.2 inc和dec指令 107
4.3 MASM常量声明 107
4.3.1 常量表达式 109
4.3.2 this和$运算符 111
4.3.3 常量表达式求值 112
4.4 MASM typedef语句 112
4.5 类型强制 113
4.6 指针数据类型 116
4.6.1 在汇编语言中使用指针 117
4.6.2 在MASM中声明指针 118
4.6.3 指针常量和指针常量
表达式 118
4.6.4 指针变量和动态内存分配 119
4.6.5 常见的指针问题 121
4.7 复合数据类型 126
4.8 字符串 126
4.8.1 以零结尾的字符串 126
4.8.2 带长度前缀的字符串 127
4.8.3 字符串描述符 128
4.8.4 字符串指针 128
4.8.5 字符串函数 128
4.9 数组 132
4.9.1 在MASM程序中声明数组 132
4.9.2 访问一维数组的元素 133
4.9.3 数组值的排序 135
4.10 多维数组 138
4.10.1 行优先顺序 138
4.10.2 列优先顺序 141
4.10.3 为多维数组分配存储空间 142
4.10.4 使用汇编语言访问多维数组
元素 143
4.11 记录/结构 144
4.11.1 MASM的结构声明 144
4.11.2 访问记录/结构字段 145
4.11.3 嵌套MASM结构 146
4.11.4 初始化结构字段 146
4.11.5 结构的数组 148
4.11.6 在记录中对齐字段 149
4.12 联合 151
4.12.1 匿名联合 153
4.12.2 可变类型 153
4.13 微软ABI注释 154
4.14 拓展阅读资料 154
4.15 自测题 154
第二部分 汇编语言程序设计
第5章 过程 158
5.1 实现过程 158
5.1.1 call和ret指令 159
5.1.2 过程中的标签 161
5.2 保存机器的状态(一) 161
5.3 过程和栈 165
5.3.1 激活记录 167
5.3.2 汇编语言的标准进入指令
序列 170
5.3.3 汇编语言的标准退出指令
序列 171
5.4 局部(自动)变量 172
5.4.1 局部变量的低级别实现 172
5.4.2 MASM的local伪指令 174
5.4.3 自动存储分配 176
5.5 参数 176
5.5.1 按值传递 177
5.5.2 按引用传递 177
5.5.3 参数的底层实现 179
5.5.4 使用proc伪指令声明参数 187
5.5.5 访问栈中的引用参数 189
5.6 调用约定和微软ABI 193
5.7 微软ABI和微软调用约定 194
5.7.1 数据类型和微软ABI 194
5.7.2 参数位置 194
5.7.3 易失性和非易失性寄存器 195
5.7.4 栈对齐 197
5.7.5 参数设置和清理(“魔法”指令的作用) 197
5.8 函数和函数的返回结果 199
5.9 递归 200
5.10 过程指针 205
5.11 过程参数 206
5.12 保存机器的状态(二) 206
5.13 微软ABI注释 208
5.14 拓展阅读资料 209
5.15 自测题 209
第6章 算术运算 212
6.1 x86-64整数算术指令 212
6.1.1 符号扩展指令和零扩展
指令 212
6.1.2 mul指令和imul指令 213
6.1.3 div指令和idiv指令 214
6.1.4 重温cmp指令 216
6.1.5 setcc指令 217
6.1.6 test指令 219
6.2 算术表达式 220
6.2.1 简单赋值语句 220
6.2.2 简单表达式 221
6.2.3 复杂表达式 223
6.2.4 可交换性运算符 227
6.3 逻辑(布尔)表达式 227
6.4 机器和算术运算的习惯用法 229
6.4.1 不使用mul或imul的乘法
运算 229
6.4.2 不使用div或idiv的除法
运算 230
6.4.3 使用AND实现模n计数器 231
6.5 浮点算术运算 231
6.5.1 x86-64上的浮点数 234
6.5.2 FPU寄存器 234
6.5.3 FPU数据类型 239
6.5.4 FPU指令集 240
6.5.5 FPU数据移动指令 240
6.5.6 转换指令 242
6.5.7 算术指令 243
6.5.8 比较指令 260
6.5.9 常量指令 269
6.5.10 超越函数指令 269
6.5.11 其他指令 271
6.6 将浮点数表达式转换为汇编
语言 272
6.6.1 将算术表达式转换为后缀
表示法 273
6.6.2 将后缀表示法转换为汇编
语言 274
6.7 SSE浮点数算术运算 275
6.7.1 SSE MXCSR寄存器 275
6.7.2 SSE浮点移动指令 276
6.7.3 SSE浮点算术指令 277
6.7.4 SSE浮点数比较 278
6.7.5 SSE浮点数转换 279
6.8 拓展阅读资料 279
6.9 自测题 280
第7章 低级控制结构 282
7.1 语句标签 282
7.1.1 在过程中使用局部符号 282
7.1.2 使用标签地址初始化数组 284
7.2 无条件控制转移 285
7.2.1 寄存器间接跳转 286
7.2.2 内存间接跳转 290
7.3 条件跳转指令 291
7.4 “蹦床” 294
7.5 条件移动指令 294
7.6 使用汇编语言实现通用控制
结构 295
7.6.1 选择结构 296
7.6.2 if/then/else语句序列 296
7.6.3 使用完整布尔求值实现复杂的
if语句 299
7.6.4 短路布尔求值 300
7.6.5 短路布尔求值和完整布尔
求值的比较 301
7.6.6 使用汇编语言高效地实现if
语句 303
7.6.7 switch/case语句 307
7.7 状态机和间接跳转 318
7.8 循环结构 325
7.8.1 while循环 325
7.8.2 repeat/until循环 326
7.8.3 无限循环 327
7.8.4 for循环 328
7.8.5 break和continue语句 329
7.8.6 寄存器和循环结构 332
7.9 循环结构的性能改进 333
7.9.1 将终止条件移动到循环的
末尾 333
7.9.2 反向执行循环 334
7.9.3 使用循环不变式计算 335
7.9.4 循环展开 336
7.9.5 使用归纳变量 337
7.10 拓展阅读资料 338
7.11 自测题 338
第8章 高级算术运算 341
8.1 扩展精度运算 341
8.1.1 扩展精度加法 341
8.1.2 扩展精度减法 343
8.1.3 扩展精度比较 344
8.1.4 扩展精度乘法 347
8.1.5 扩展精度除法 350
8.1.6 扩展精度取反操作 359
8.1.7 扩展精度AND运算 360
8.1.8 扩展精度OR运算 361
8.1.9 扩展精度XOR运算 361
8.1.10 扩展精度NOT运算 361
8.1.11 扩展精度移位运算 362
8.1.12 扩展精度循环移位运算 364
8.2 对不同大小的操作数进行运算 365
8.3 十进制算术运算 366
8.3.1 字面BCD常量 367
8.3.2 使用FPU的压缩十进制算术
运算 367
8.4 拓展阅读资料 368
8.5 自测题 368
第9章 数值转换 370
9.1 将数值转换为字符串 370
9.1.1 将数值转换为十六进制
字符串 370
9.1.2 将扩展精度十六进制值转换
为字符串 376
9.1.3 将无符号十进制值转换为
字符串 377
9.1.4 将有符号整数值转换为
字符串 383
9.1.5 将扩展精度无符号整数转换为
字符串 383
9.1.6 将扩展精度有符号十进制值
转换为字符串 387
9.1.7 格式化转换 388
9.1.8 将浮点值转换为字符串 392
9.2 字符串到数值的转换例程 413
9.2.1 将十进制字符串转换为
整数 413
9.2.2 将十六进制字符串转换为
数值形式 421
9.2.3 将无符号十进制字符串转换为
整数 427
9.2.4 扩展精度字符串到无符号
整数的转换 430
9.2.5 扩展精度有符号十进制
字符串到整数的转换 432
9.2.6 实数字符串到浮点值的
转换 433
9.3 拓展阅读资料 442
9.4 自测题 442
第10章 表查找 443
10.1 表 443
10.1.1 通过表查找进行函数计算 443
10.1.2 生成表 448
10.1.3 表查找的性能 450
10.2 拓展阅读资料 450
10.3 自测题 450
第11章 SIMD指令 451
11.1 SSE/AVX体系结构 451
11.2 流数据类型 452
11.3 使用cpuid区分指令集 453
11.4 完整的段语法和段对齐 458
11.5 SSE、AVX和AVX2内存操作数
对齐 459
11.6 SIMD数据移动指令 461
11.6.1 (v)movd和(v)movq指令 461
11.6.2 (v)movaps、(v)movapd和(v)movdqa指令 462
11.6.3 (v)movups、(v)movupd和(v)movdqu指令 463
11.6.4 对齐和未对齐移动指令的
性能 464
11.6.5 (v)movlps和(v)movlpd
指令 466
11.6.6 movhps和movhpd指令 467
11.6.7 vmovhps和vmovhpd指令 468
11.6.8 movlhps和vmovlhps指令 469
11.6.9 movhlps和vmovhlps指令 469
11.6.10 (v)movshdup和(v)movsldup指令 470
11.6.11 (v)movddup指令 470
11.6.12 (v)lddqu指令 471
11.6.13 性能问题和SIMD移动
指令 471
11.6.14 关于SIMD移动指令的一些
说明 472
11.7 混排和解包指令 473
11.7.1 (v)pshufb指令 473
11.7.2 (v)pshufd指令 475
11.7.3 (v)pshuflw和(v)pshufhw
指令 475
11.7.4 shufps和shufpd指令 477
11.7.5 vshufps和vshufpd指令 478
11.7.6 (v)unpcklps、(v)unpckhps、
(v)unpcklpd和(v)unpckhpd
指令 479
11.7.7 整数解包指令 482
11.7.8 (v)pextrb、(v)pextrw、(v)pextrd和(v)pextrq指令 484
11.7.9 (v)pinsrb、(v)pinsrw、(v)pinsrd和(v)pinsrq指令 485
11.7.10 (v)extractps和(v)insertps
指令 485
11.8 SIMD算术和逻辑运算 486
11.9 SIMD逻辑(按位操作)指令 487
11.9.1 (v)ptest指令 488
11.9.2 字节移位指令 488
11.9.3 位移位指令 488
11.10 SIMD整数算术指令 489
11.10.1 SIMD整数加法 489
11.10.2 水平加法运算 491
11.10.3 双字大小的水平加法
运算 492
11.10.4 SIMD整数减法运算 493
11.10.5 SIMD整数乘法运算 494
11.10.6 SIMD整数平均值 496
11.10.7 SIMD整数的最小值和
最大值 496
11.10.8 SIMD整数的绝对值 497
11.10.9 SIMD整数符号调整指令 497
11.10.10 SIMD整数比较指令 498
11.10.11 整数转换 501
11.11 SIMD浮点算术运算 504
11.12 SIMD浮点比较指令 506
11.12.1 SSE和AVX的比较指令 507
11.12.2 无序比较与有序比较 508
11.12.3 信号比较与安静比较 508
11.12.4 指令的同义词 508
11.12.5 AVX扩展比较 509
11.12.6 使用SIMD比较指令 510
11.12.7 (v)movmskps和
(v) movmskpd指令 510
11.13 浮点转换指令 512
11.14 对齐SIMD内存访问 513
11.15 对齐字、双字和四字对象的
地址 515
11.16 使用相同值的几个副本填充
XMM寄存器 515
11.17 将一些常用常量加载到XMM
和YMM寄存器中 516
11.18 设置、清除、反转和测试SSE
寄存器中的单个位 518
11.19 使用单个递增索引来处理两个
向量 519
11.20 将两个地址对齐到同一个内存
边界 520
11.21 处理长度不是SSE/AVX寄存器
大小倍数的数据块 521
11.22 CPU功能的动态测试 522
11.23 MASM include伪指令 530
11.24 其他SIMD指令 531
11.25 拓展阅读资料 531
11.26 自测题 532
第12章 位操作 534
12.1 什么是位数据 534
12.2 操作位的指令 535
12.2.1 and指令 535
12.2.2 or指令 536
12.2.3 xor指令 537
12.2.4 通过逻辑指令修改
标志位 537
12.2.5 位测试指令 539
12.2.6 使用移位和循环移位指令操
作位 540
12.3 作为位累加器的进位标志位 540
12.4 位串的打包和解包 541
12.5 提取位和创建位掩码的BMI1
指令 546
12.6 合并位集和分配位串 550
12.7 使用BMI2指令合并和分配
位串 552
12.8 打包的位串数组 553
12.9 查找位 556
12.10 统计位的个数 558
12.11 反转位串 559
12.12 合并位串 560
12.13 提取位串 561
12.14 搜索位模式 561
12.15 拓展阅读资料 562
12.16 自测题 562
第13章 宏和MASM编译时
语言 564
13.1 编译时语言的概述 564
13.2 echo和“.err”伪指令 565
13.3 编译时常量和变量 565
13.4 编译时表达式和运算符 566
13.4.1 MASM转义运算符(!) 566
13.4.2 MASM求值运算符(%) 566
13.4.3 catstr伪指令 566
13.4.4 instr伪指令 567
13.4.5 sizestr伪指令 567
13.4.6 substr伪指令 567
13.5 条件汇编(编译时决策) 568
13.6 重复汇编(编译时循环) 570
13.7 宏(编译时过程) 573
13.8 标准宏 573
13.9 宏参数 574
13.9.1 标准宏参数展开 575
13.9.2 可选和必需的宏参数 577
13.9.3 默认宏参数值 579
13.9.4 具有可变数量参数的宏 579
13.9.5 宏展开运算符(&) 580
13.10 宏中的局部符号 581
13.11 exitm伪指令 582
13.12 MASM宏函数语法 583
13.13 宏作为编译时过程和函数 584
13.14 编写编译时“程序” 585
13.14.1 在编译时构建数据表 585
13.14.2 展开循环 588
13.15 模拟高级语言的过程调用 589
13.15.1 模拟高级语言的调用
(无参数) 589
13.15.2 模拟高级语言的调用
(带有一个参数) 590
13.15.3 使用opattr确定参数
类型 591
13.15.4 模拟高级语言的调用
(带有固定数量的参数) 593
13.15.5 模拟高级语言的调用
(带有可变参数列表) 597
13.16 调用宏 600
13.17 高级宏参数解析 600
13.17.1 检测字符串字面常量 601
13.17.2 检测实数常量 602
13.17.3 检测寄存器 610
13.17.4 编译时数组 614
13.18 使用宏编写宏 618
13.19 编译时程序的性能 621
13.20 拓展阅读资料 621
13.21 自测题 621
第14章 串指令 623
14.1 x86-64串指令 623
14.1.1 rep、repe、repz以及repnz和repne前缀 623
14.1.2 方向标志位 624
14.1.3 movs指令 624
14.1.4 cmps指令 628
14.1.5 scas指令 629
14.1.6 stos指令 630
14.1.7 lods指令 631
14.1.8 使用lods和stos构建复杂的
串函数 631
14.2 x86-64串指令的性能 632
14.3 SIMD串指令 632
14.3.1 打包比较的操作数大小 632
14.3.2 比较的类型 633
14.3.3 结果的极性 634
14.3.4 输出处理 634
14.3.5 打包字符串比较长度 634
14.3.6 打包字符串比较结果 636
14.4 对齐和MMU页 636
14.5 拓展阅读资料 637
14.6 自测题 637
第15章 管理复杂的项目 639
15.1 include伪指令 639
15.2 忽略重复包含的操作 640
15.3 汇编单元和外部伪指令 640
15.4 MASM中的头文件 642
15.5 externdef伪指令 642
15.6 分离式编译 643
15.7 makefile简介 650
15.7.1 基本的makefile语法 650
15.7.2 make依赖项 651
15.7.3 clean和touch 654
15.8 微软链接器和库代码 655
15.9 对象文件和库文件对程序大小的
影响 656
15.10 拓展阅读资料 657
15.11 自测题 657
第16章 独立的汇编语言程序 658
16.1 独立的“Hello,world!”程序 658
16.2 头文件和Windows接口 660
16.3 Win32 API和Windows ABI 662
16.4 构建独立的控制台应用程序 662
16.5 构建独立的GUI应用程序 662
16.6 Windows API的MessageBox
函数概述 663
16.7 Windows文件I/O 664
16.8 Windows应用程序 676
16.9 拓展阅读资料 677
16.10 自测题 677
附录
附录A 安装和使用
Visual Studio 678
附录B 自测题参考答案 682
The Art of 64-Bit Assembly: x86-64 Machine Organization and Programming
译者序
推荐序
前言
致谢
第一部分 计算机的组成结构
第1章 汇编语言的第一个程序 2
1.1 先决条件 2
1.2 在计算机上安装MASM 3
1.3 在计算机上安装文本编辑器 3
1.4 MASM程序的结构剖析 3
1.5 运行第一个MASM程序 4
1.6 运行第一个MASM和C++的混合
程序 4
1.7 英特尔x86-64 CPU系列简介 6
1.8 内存子系统 9
1.9 在MASM中声明内存变量 10
1.9.1 将内存地址与变量关联 11
1.9.2 将数据类型与变量关联 12
1.10 在MASM中声明(命名)常量 12
1.11 基本的机器指令 13
1.11.1 mov指令 13
1.11.2 指令操作数的类型检查 14
1.11.3 add和sub指令 15
1.11.4 lea指令 15
1.11.5 call和ret指令以及MASM
过程 16
1.12 调用C/C++过程 17
1.13 “Hello, world!”程序 18
1.14 在汇编语言中返回函数结果 19
1.15 自动化构建过程 24
1.16 微软ABI注释 25
1.16.1 变量大小 25
1.16.2 寄存器的用途 28
1.16.3 栈对齐 28
1.17 拓展阅读资料 28
1.18 自测题 29
第2章 计算机数据表示和运算 31
2.1 数制系统 31
2.1.1 十进制数制系统的回顾 31
2.1.2 二进制数制系统 32
2.1.3 二进制约定 32
2.2 十六进制数制系统 33
2.3 关于数字与表示的注释 34
2.4 数据组织 36
2.4.1 位 36
2.4.2 半字节 36
2.4.3 字节 37
2.4.4 字 38
2.4.5 双字 39
2.4.6 四字和八字 39
2.5 位的逻辑运算 39
2.5.1 逻辑与运算 40
2.5.2 逻辑或运算 40
2.5.3 逻辑异或运算 40
2.5.4 逻辑非运算 41
2.6 二进制数和位串的逻辑运算 41
2.7 有符号数和无符号数 45
2.8 符号扩展和零扩展 49
2.9 符号缩减和饱和法 49
2.10 简要回顾:控制转移指令概述 50
2.10.1 jmp指令 50
2.10.2 条件跳转指令 51
2.10.3 cmp指令和相应的条件
跳转 52
2.10.4 条件跳转的同义词 53
2.11 移位和循环移位 54
2.12 位字段和打包数据 57
2.13 IEEE浮点数格式 63
2.13.1 单精度格式 64
2.13.2 双精度格式 65
2.13.3 扩展精度格式 65
2.13.4 规范化浮点值 65
2.13.5 非数值数据 66
2.13.6 MASM对浮点值的支持 66
2.14 BCD表示法 67
2.15 字符 67
2.15.1 ASCII字符编码 68
2.15.2 MASM对ASCII字符的
支持 69
2.16 Unicode字符集 70
2.16.1 Unicode码位 70
2.16.2 Unicode码平面 70
2.16.3 Unicode编码 71
2.17 MASM对Unicode的支持 72
2.18 拓展阅读资料 72
2.19 自测题 72
第3章 内存的访问和组织 76
3.1 运行时的内存组织 76
3.1.1 “.code”段 77
3.1.2 “.data”段 77
3.1.3 “.const”段 78
3.1.4 “.data?”段 79
3.1.5 程序中声明段的组织方式 79
3.1.6 内存访问和4KB内存管理
单元页 80
3.2 MASM如何为变量分配内存 81
3.3 标签声明 82
3.4 小端模式和大端模式的数据组织
方式 82
3.5 内存访问 84
3.6 MASM对数据对齐的支持 85
3.7 x86-64的寻址模式 87
3.7.1 x86-64的寄存器寻址模式 88
3.7.2 x86-64的64位内存寻址模式 88
3.7.3 不支持大地址的应用程序 91
3.8 地址表达式 94
3.9 栈段以及push和pop指令 97
3.9.1 基本的push指令 97
3.9.2 基本的pop指令 98
3.9.3 使用push和pop指令保存
寄存器的状态 99
3.10 栈 99
3.11 其他push和pop指令 102
3.12 不通过弹出栈从栈中移除数据 102
3.13 不通过弹出栈访问压入栈的
数据 103
3.14 微软ABI注释 104
3.15 拓展阅读资料 104
3.16 自测题 104
第4章 常量、变量和数据类型 106
4.1 imul指令 106
4.2 inc和dec指令 107
4.3 MASM常量声明 107
4.3.1 常量表达式 109
4.3.2 this和$运算符 111
4.3.3 常量表达式求值 112
4.4 MASM typedef语句 112
4.5 类型强制 113
4.6 指针数据类型 116
4.6.1 在汇编语言中使用指针 117
4.6.2 在MASM中声明指针 118
4.6.3 指针常量和指针常量
表达式 118
4.6.4 指针变量和动态内存分配 119
4.6.5 常见的指针问题 121
4.7 复合数据类型 126
4.8 字符串 126
4.8.1 以零结尾的字符串 126
4.8.2 带长度前缀的字符串 127
4.8.3 字符串描述符 128
4.8.4 字符串指针 128
4.8.5 字符串函数 128
4.9 数组 132
4.9.1 在MASM程序中声明数组 132
4.9.2 访问一维数组的元素 133
4.9.3 数组值的排序 135
4.10 多维数组 138
4.10.1 行优先顺序 138
4.10.2 列优先顺序 141
4.10.3 为多维数组分配存储空间 142
4.10.4 使用汇编语言访问多维数组
元素 143
4.11 记录/结构 144
4.11.1 MASM的结构声明 144
4.11.2 访问记录/结构字段 145
4.11.3 嵌套MASM结构 146
4.11.4 初始化结构字段 146
4.11.5 结构的数组 148
4.11.6 在记录中对齐字段 149
4.12 联合 151
4.12.1 匿名联合 153
4.12.2 可变类型 153
4.13 微软ABI注释 154
4.14 拓展阅读资料 154
4.15 自测题 154
第二部分 汇编语言程序设计
第5章 过程 158
5.1 实现过程 158
5.1.1 call和ret指令 159
5.1.2 过程中的标签 161
5.2 保存机器的状态(一) 161
5.3 过程和栈 165
5.3.1 激活记录 167
5.3.2 汇编语言的标准进入指令
序列 170
5.3.3 汇编语言的标准退出指令
序列 171
5.4 局部(自动)变量 172
5.4.1 局部变量的低级别实现 172
5.4.2 MASM的local伪指令 174
5.4.3 自动存储分配 176
5.5 参数 176
5.5.1 按值传递 177
5.5.2 按引用传递 177
5.5.3 参数的底层实现 179
5.5.4 使用proc伪指令声明参数 187
5.5.5 访问栈中的引用参数 189
5.6 调用约定和微软ABI 193
5.7 微软ABI和微软调用约定 194
5.7.1 数据类型和微软ABI 194
5.7.2 参数位置 194
5.7.3 易失性和非易失性寄存器 195
5.7.4 栈对齐 197
5.7.5 参数设置和清理(“魔法”指令的作用) 197
5.8 函数和函数的返回结果 199
5.9 递归 200
5.10 过程指针 205
5.11 过程参数 206
5.12 保存机器的状态(二) 206
5.13 微软ABI注释 208
5.14 拓展阅读资料 209
5.15 自测题 209
第6章 算术运算 212
6.1 x86-64整数算术指令 212
6.1.1 符号扩展指令和零扩展
指令 212
6.1.2 mul指令和imul指令 213
6.1.3 div指令和idiv指令 214
6.1.4 重温cmp指令 216
6.1.5 setcc指令 217
6.1.6 test指令 219
6.2 算术表达式 220
6.2.1 简单赋值语句 220
6.2.2 简单表达式 221
6.2.3 复杂表达式 223
6.2.4 可交换性运算符 227
6.3 逻辑(布尔)表达式 227
6.4 机器和算术运算的习惯用法 229
6.4.1 不使用mul或imul的乘法
运算 229
6.4.2 不使用div或idiv的除法
运算 230
6.4.3 使用AND实现模n计数器 231
6.5 浮点算术运算 231
6.5.1 x86-64上的浮点数 234
6.5.2 FPU寄存器 234
6.5.3 FPU数据类型 239
6.5.4 FPU指令集 240
6.5.5 FPU数据移动指令 240
6.5.6 转换指令 242
6.5.7 算术指令 243
6.5.8 比较指令 260
6.5.9 常量指令 269
6.5.10 超越函数指令 269
6.5.11 其他指令 271
6.6 将浮点数表达式转换为汇编
语言 272
6.6.1 将算术表达式转换为后缀
表示法 273
6.6.2 将后缀表示法转换为汇编
语言 274
6.7 SSE浮点数算术运算 275
6.7.1 SSE MXCSR寄存器 275
6.7.2 SSE浮点移动指令 276
6.7.3 SSE浮点算术指令 277
6.7.4 SSE浮点数比较 278
6.7.5 SSE浮点数转换 279
6.8 拓展阅读资料 279
6.9 自测题 280
第7章 低级控制结构 282
7.1 语句标签 282
7.1.1 在过程中使用局部符号 282
7.1.2 使用标签地址初始化数组 284
7.2 无条件控制转移 285
7.2.1 寄存器间接跳转 286
7.2.2 内存间接跳转 290
7.3 条件跳转指令 291
7.4 “蹦床” 294
7.5 条件移动指令 294
7.6 使用汇编语言实现通用控制
结构 295
7.6.1 选择结构 296
7.6.2 if/then/else语句序列 296
7.6.3 使用完整布尔求值实现复杂的
if语句 299
7.6.4 短路布尔求值 300
7.6.5 短路布尔求值和完整布尔
求值的比较 301
7.6.6 使用汇编语言高效地实现if
语句 303
7.6.7 switch/case语句 307
7.7 状态机和间接跳转 318
7.8 循环结构 325
7.8.1 while循环 325
7.8.2 repeat/until循环 326
7.8.3 无限循环 327
7.8.4 for循环 328
7.8.5 break和continue语句 329
7.8.6 寄存器和循环结构 332
7.9 循环结构的性能改进 333
7.9.1 将终止条件移动到循环的
末尾 333
7.9.2 反向执行循环 334
7.9.3 使用循环不变式计算 335
7.9.4 循环展开 336
7.9.5 使用归纳变量 337
7.10 拓展阅读资料 338
7.11 自测题 338
第8章 高级算术运算 341
8.1 扩展精度运算 341
8.1.1 扩展精度加法 341
8.1.2 扩展精度减法 343
8.1.3 扩展精度比较 344
8.1.4 扩展精度乘法 347
8.1.5 扩展精度除法 350
8.1.6 扩展精度取反操作 359
8.1.7 扩展精度AND运算 360
8.1.8 扩展精度OR运算 361
8.1.9 扩展精度XOR运算 361
8.1.10 扩展精度NOT运算 361
8.1.11 扩展精度移位运算 362
8.1.12 扩展精度循环移位运算 364
8.2 对不同大小的操作数进行运算 365
8.3 十进制算术运算 366
8.3.1 字面BCD常量 367
8.3.2 使用FPU的压缩十进制算术
运算 367
8.4 拓展阅读资料 368
8.5 自测题 368
第9章 数值转换 370
9.1 将数值转换为字符串 370
9.1.1 将数值转换为十六进制
字符串 370
9.1.2 将扩展精度十六进制值转换
为字符串 376
9.1.3 将无符号十进制值转换为
字符串 377
9.1.4 将有符号整数值转换为
字符串 383
9.1.5 将扩展精度无符号整数转换为
字符串 383
9.1.6 将扩展精度有符号十进制值
转换为字符串 387
9.1.7 格式化转换 388
9.1.8 将浮点值转换为字符串 392
9.2 字符串到数值的转换例程 413
9.2.1 将十进制字符串转换为
整数 413
9.2.2 将十六进制字符串转换为
数值形式 421
9.2.3 将无符号十进制字符串转换为
整数 427
9.2.4 扩展精度字符串到无符号
整数的转换 430
9.2.5 扩展精度有符号十进制
字符串到整数的转换 432
9.2.6 实数字符串到浮点值的
转换 433
9.3 拓展阅读资料 442
9.4 自测题 442
第10章 表查找 443
10.1 表 443
10.1.1 通过表查找进行函数计算 443
10.1.2 生成表 448
10.1.3 表查找的性能 450
10.2 拓展阅读资料 450
10.3 自测题 450
第11章 SIMD指令 451
11.1 SSE/AVX体系结构 451
11.2 流数据类型 452
11.3 使用cpuid区分指令集 453
11.4 完整的段语法和段对齐 458
11.5 SSE、AVX和AVX2内存操作数
对齐 459
11.6 SIMD数据移动指令 461
11.6.1 (v)movd和(v)movq指令 461
11.6.2 (v)movaps、(v)movapd和(v)movdqa指令 462
11.6.3 (v)movups、(v)movupd和(v)movdqu指令 463
11.6.4 对齐和未对齐移动指令的
性能 464
11.6.5 (v)movlps和(v)movlpd
指令 466
11.6.6 movhps和movhpd指令 467
11.6.7 vmovhps和vmovhpd指令 468
11.6.8 movlhps和vmovlhps指令 469
11.6.9 movhlps和vmovhlps指令 469
11.6.10 (v)movshdup和(v)movsldup指令 470
11.6.11 (v)movddup指令 470
11.6.12 (v)lddqu指令 471
11.6.13 性能问题和SIMD移动
指令 471
11.6.14 关于SIMD移动指令的一些
说明 472
11.7 混排和解包指令 473
11.7.1 (v)pshufb指令 473
11.7.2 (v)pshufd指令 475
11.7.3 (v)pshuflw和(v)pshufhw
指令 475
11.7.4 shufps和shufpd指令 477
11.7.5 vshufps和vshufpd指令 478
11.7.6 (v)unpcklps、(v)unpckhps、
(v)unpcklpd和(v)unpckhpd
指令 479
11.7.7 整数解包指令 482
11.7.8 (v)pextrb、(v)pextrw、(v)pextrd和(v)pextrq指令 484
11.7.9 (v)pinsrb、(v)pinsrw、(v)pinsrd和(v)pinsrq指令 485
11.7.10 (v)extractps和(v)insertps
指令 485
11.8 SIMD算术和逻辑运算 486
11.9 SIMD逻辑(按位操作)指令 487
11.9.1 (v)ptest指令 488
11.9.2 字节移位指令 488
11.9.3 位移位指令 488
11.10 SIMD整数算术指令 489
11.10.1 SIMD整数加法 489
11.10.2 水平加法运算 491
11.10.3 双字大小的水平加法
运算 492
11.10.4 SIMD整数减法运算 493
11.10.5 SIMD整数乘法运算 494
11.10.6 SIMD整数平均值 496
11.10.7 SIMD整数的最小值和
最大值 496
11.10.8 SIMD整数的绝对值 497
11.10.9 SIMD整数符号调整指令 497
11.10.10 SIMD整数比较指令 498
11.10.11 整数转换 501
11.11 SIMD浮点算术运算 504
11.12 SIMD浮点比较指令 506
11.12.1 SSE和AVX的比较指令 507
11.12.2 无序比较与有序比较 508
11.12.3 信号比较与安静比较 508
11.12.4 指令的同义词 508
11.12.5 AVX扩展比较 509
11.12.6 使用SIMD比较指令 510
11.12.7 (v)movmskps和
(v) movmskpd指令 510
11.13 浮点转换指令 512
11.14 对齐SIMD内存访问 513
11.15 对齐字、双字和四字对象的
地址 515
11.16 使用相同值的几个副本填充
XMM寄存器 515
11.17 将一些常用常量加载到XMM
和YMM寄存器中 516
11.18 设置、清除、反转和测试SSE
寄存器中的单个位 518
11.19 使用单个递增索引来处理两个
向量 519
11.20 将两个地址对齐到同一个内存
边界 520
11.21 处理长度不是SSE/AVX寄存器
大小倍数的数据块 521
11.22 CPU功能的动态测试 522
11.23 MASM include伪指令 530
11.24 其他SIMD指令 531
11.25 拓展阅读资料 531
11.26 自测题 532
第12章 位操作 534
12.1 什么是位数据 534
12.2 操作位的指令 535
12.2.1 and指令 535
12.2.2 or指令 536
12.2.3 xor指令 537
12.2.4 通过逻辑指令修改
标志位 537
12.2.5 位测试指令 539
12.2.6 使用移位和循环移位指令操
作位 540
12.3 作为位累加器的进位标志位 540
12.4 位串的打包和解包 541
12.5 提取位和创建位掩码的BMI1
指令 546
12.6 合并位集和分配位串 550
12.7 使用BMI2指令合并和分配
位串 552
12.8 打包的位串数组 553
12.9 查找位 556
12.10 统计位的个数 558
12.11 反转位串 559
12.12 合并位串 560
12.13 提取位串 561
12.14 搜索位模式 561
12.15 拓展阅读资料 562
12.16 自测题 562
第13章 宏和MASM编译时
语言 564
13.1 编译时语言的概述 564
13.2 echo和“.err”伪指令 565
13.3 编译时常量和变量 565
13.4 编译时表达式和运算符 566
13.4.1 MASM转义运算符(!) 566
13.4.2 MASM求值运算符(%) 566
13.4.3 catstr伪指令 566
13.4.4 instr伪指令 567
13.4.5 sizestr伪指令 567
13.4.6 substr伪指令 567
13.5 条件汇编(编译时决策) 568
13.6 重复汇编(编译时循环) 570
13.7 宏(编译时过程) 573
13.8 标准宏 573
13.9 宏参数 574
13.9.1 标准宏参数展开 575
13.9.2 可选和必需的宏参数 577
13.9.3 默认宏参数值 579
13.9.4 具有可变数量参数的宏 579
13.9.5 宏展开运算符(&) 580
13.10 宏中的局部符号 581
13.11 exitm伪指令 582
13.12 MASM宏函数语法 583
13.13 宏作为编译时过程和函数 584
13.14 编写编译时“程序” 585
13.14.1 在编译时构建数据表 585
13.14.2 展开循环 588
13.15 模拟高级语言的过程调用 589
13.15.1 模拟高级语言的调用
(无参数) 589
13.15.2 模拟高级语言的调用
(带有一个参数) 590
13.15.3 使用opattr确定参数
类型 591
13.15.4 模拟高级语言的调用
(带有固定数量的参数) 593
13.15.5 模拟高级语言的调用
(带有可变参数列表) 597
13.16 调用宏 600
13.17 高级宏参数解析 600
13.17.1 检测字符串字面常量 601
13.17.2 检测实数常量 602
13.17.3 检测寄存器 610
13.17.4 编译时数组 614
13.18 使用宏编写宏 618
13.19 编译时程序的性能 621
13.20 拓展阅读资料 621
13.21 自测题 621
第14章 串指令 623
14.1 x86-64串指令 623
14.1.1 rep、repe、repz以及repnz和repne前缀 623
14.1.2 方向标志位 624
14.1.3 movs指令 624
14.1.4 cmps指令 628
14.1.5 scas指令 629
14.1.6 stos指令 630
14.1.7 lods指令 631
14.1.8 使用lods和stos构建复杂的
串函数 631
14.2 x86-64串指令的性能 632
14.3 SIMD串指令 632
14.3.1 打包比较的操作数大小 632
14.3.2 比较的类型 633
14.3.3 结果的极性 634
14.3.4 输出处理 634
14.3.5 打包字符串比较长度 634
14.3.6 打包字符串比较结果 636
14.4 对齐和MMU页 636
14.5 拓展阅读资料 637
14.6 自测题 637
第15章 管理复杂的项目 639
15.1 include伪指令 639
15.2 忽略重复包含的操作 640
15.3 汇编单元和外部伪指令 640
15.4 MASM中的头文件 642
15.5 externdef伪指令 642
15.6 分离式编译 643
15.7 makefile简介 650
15.7.1 基本的makefile语法 650
15.7.2 make依赖项 651
15.7.3 clean和touch 654
15.8 微软链接器和库代码 655
15.9 对象文件和库文件对程序大小的
影响 656
15.10 拓展阅读资料 657
15.11 自测题 657
第16章 独立的汇编语言程序 658
16.1 独立的“Hello,world!”程序 658
16.2 头文件和Windows接口 660
16.3 Win32 API和Windows ABI 662
16.4 构建独立的控制台应用程序 662
16.5 构建独立的GUI应用程序 662
16.6 Windows API的MessageBox
函数概述 663
16.7 Windows文件I/O 664
16.8 Windows应用程序 676
16.9 拓展阅读资料 677
16.10 自测题 677
附录
附录A 安装和使用
Visual Studio 678
附录B 自测题参考答案 682





