本书源于作者的经典书籍The Art of Assembly Language,从32位汇编语言升级为64位汇编语言,基于MASM讲解x86-64CPU上汇编语言的编程艺术。本书从计算机的组成结构开始介绍,包括计算机数据表示和运算,以及内存的访问和组织等。之后详细讲解汇编语言程序设计,涉及过程和算术运算的相关知识,再通过低级控制结构过渡到高级主题,如表查找和位操作。此外,还探索了x87浮点单元、SIMD指令,以及MASM的宏工具。
本书源于作者的经典书籍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
本书是作者30年工作的结晶。本书最早的版本是作者在加州理工大学波莫纳分校和加州大学河滨分校提供给学生的课堂笔记,标题是“如何使用8088汇编语言为IBM PC编程”。学生们和作者的一个好朋友玛丽·菲利普斯(Mary Philips)提出了很多宝贵的意见。比尔·波洛克(Bill Pollock)最先在互联网上发现了课堂笔记的早期版本,并在卡罗尔·朱拉多(Karol Jurado)的帮助下,使The Art of Assembly Language第1版于2003年正式出版。
后来,基于数以千计读者的意见和反馈,以及在No Starch出版社的比尔·波洛克(Bill Pollock)、艾莉森·彼得森(Alison Peterson)、安塞尔·斯塔顿(Ansel Staton)、莱利·霍夫曼(Riley Hoffman)、梅根·邓查克(Megan Dunchak)、琳达·雷克滕瓦尔德(Linda Recktenwald)、苏珊·格利纳特·史蒂文斯(Susan Glinert Stevens)、南希·贝尔(Nancy Bell)和技术审稿人内森·贝克(Nathan Baker)的支持下,The Art of Assembly Language的第2版于2010年出版。
转眼十年过去了,The Art of Assembly Language(作者将其简称为AoA)渐渐失去了流行度,因为该书所阐述的内容与英特尔x86的35年前的32位设计紧密关联。今天,打算学习80x86汇编语言的人可能想学习在较新的x86-64 CPU上的64位汇编语言。因此,鉴于32位的AoA基于HLA,在2020年年初,作者即开始使用MASM,逐步将陈旧的32位AoA转换为64位的。
刚开始着手这个将AoA从32位转为64位的项目时,作者曾天真地认为只需要把少量HLA程序翻译成MASM,调整一些文本,花费少量的精力即可。结果证明作者的想法大错特错。No Starch出版社的工作人员希望在可读性和易理解性方面取得突破,托尼·特里贝利(Tony Tribelli)在对这本书中的每一行文本和代码进行技术审查时所做的工作令人难以置信。因此,这个从32位到64位转换项目的工作相当于从头开始撰写一本新书。不过至少所有的努力都是值得的,相信读者能从我们辛勤编撰的成果中有所领悟。
关于本书中所提供的源代码
本书中包含了大量的x86-64汇编语言(以及C/C 语言)源代码。通常情况下,源代码有三种形式,即代码片段(code snippet)、单一汇编语言过程或函数(single assembly language procedure or function)以及完整程序(full-blown program)。
代码片段是程序的片段。代码片段不是独立的程序,并且不能使用MASM进行编译或汇编(如果是C/C 源代码,则不能使用C/C 编译器编译这些代码片段)。本书中之所以使用代码片段,是为了说明一个观点或提供一个编程技术的小例子。本书中代码片段的典型示例如下:
someConst = 5
.
.
.
mov eax, someConst
垂直省略号表示可能出现在其位置的任意代码(需要注意的是,并非所有代码片段都使用垂直省略号)。
汇编语言过程或函数也不是独立的程序。虽然读者可以对本书中出现的许多汇编语言过程加以汇编(只需将本书中的代码直接复制到编辑器中,然后在生成的文本文件上运行MASM),但这些过程并不会自行执行。代码片段和汇编语言过程的主要区别在于:汇编语言过程包含在本书可下载的源文件中(下载网址为https://artofasm.randallhyde.com/)。
在本书中,可以编译和执行的完整程序被标记为程序清单(listing),它有“程序清单C-N”形式的编号或标识符,其中C是章编号,N是顺序递增的程序清单编号,每章中编号N从1开始。以下是本书中出现的程序清单示例。
程序清单1-3 MASM程序(listing1-3.asm文件),被程序清单1-2中的C 程序调用
; 程序清单1-3
; 一个简单的MASM模块,包含一个空函数,被程序清单1-2中的C 代码调用。
.CODE
; (有关option伪指令的说明,请参见后续正文。)
option casemap:none
; 以下是“asmFunc”函数的定义。
public asmFunc
asmFunc PROC
; 空函数,直接返回到C 代码。
ret ; 返回到调用方
asmFunc ENDP
END
与汇编语言过程一样,在作者的网站(https://artofasm.randallhyde.com/)上也可以找到本书所有的程序清单。该网站包含了本书所有源代码文件以及相关资源信息(例如勘误表、电子版和其他有用信息)的页面。为了便于阅读,有几个章节将程序清单编号附加到过程和宏上,这些过程和宏不是完整的程序。有些程序清单只用来演示MASM的语法错误,因此无法运行。源代码发行包中仍然包含这些程序清单的源代码,代码名称为对应的程序清
单名。
通常情况下,本书使用build命令和示例输出跟踪可执行的程序清单。以下是一个典型示例(用户输入内容以黑体字的形式给出):
C:\>build listing4-7
C:\>echo off
Assembling: listing4-7.asm
c.cpp
C:\>listing4-7
Calling Listing 4-7:
aString: maxLen:20, len:20, string data:'Initi
兰德尔·海德
(Randall Hyde)
嵌入式软件工程师,曾在医疗、核能、消费电子和娱乐行业工作。他在大学教授汇编语言编程超过10年,多年来为嵌入式和商业应用程序编写了数十万行汇编代码。著有The Art of Assembly Language和Write Great Code系列书籍,均由No Starch出版社出版。
目 录
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 在M