IA-32平台的寄存器:
寄存器 | 描述 |
通用 | 8个32位寄存器,用于存储正在处理的数据 |
段 | 6个16位寄存器,用于处理内存访问 |
指令指针 | 单一的32位寄存器,指向要执行的下一条指令码 |
浮点数据 | 8个80位寄存器,用于浮点数学数据 |
控制 | 5个32位寄存器,用于确定处理器的操作模式 |
调试 | 8个32位寄存器,用于在调试处理器时包含信息 |
IA-32平台的通用寄存器(32位):
寄存器 | 描述 |
EAX | 用于操作数和结果数据的累加器 |
EBX | 指向数据内存段中的数据的指针 |
ECX | 字符串和循环操作的计数器 |
EDX | I/O指针 |
EDI | 用于字符串操作的目标的数据指针 |
ESI | 用于字符串操作的源的数据指针 |
ESP | 堆栈指针 |
EBP | 堆栈数据指针 |
IA-32平台的段寄存器(16位):
段寄存器 | 描述 |
CS | 代码段 |
DS | 数据段 |
SS | 堆栈段 |
ES | 附加段指针 |
FS | 附加段指针 |
GS | 附加段指针 |
IA-32平台的控制寄存器:
控制寄存器 | 描述 |
CR0 | 控制操作模式和处理器状态的系统标志 |
CR1 | 当前没有使用 |
CR2 | 内存页面错误信息 |
CR3 | 内存页面目录信息 |
CR4 | 支持处理器特性和说明处理器特性能力的标志 |
IA-32平台的状态标志:
标志 | 位 | 名称 |
CF | 0 | 进位标志 |
PF | 2 | 奇偶检验标志 |
AF | 4 | 辅助进位标志 |
ZF | 6 | 零标志 |
SF | 7 | 符号标志 |
OF | 11 | 溢出标志 |
IA-32平台的系统标志:
标志 | 位 | 名称 |
TF | 8 | 陷阱标志 |
IF | 9 | 中断使能标志 |
IOPL | 12和13 | I/O特权级别标志 |
NT | 14 | 嵌套任务标志 |
RF | 16 | 恢复标志 |
VM | 17 | 虚拟8086模式标志 |
AC | 18 | 对准检查标志 |
VIF | 19 | 虚拟中断标志 |
VIP | 20 | 虚拟中断挂起标志 |
ID | 21 | 识别标志 |
IA-32平台的FPU寄存器:
FPU寄存器 | 描述 |
数据寄存器 | 用于浮点数据的8个80位寄存器 |
状态寄存器 | 报告FPU状态的16位寄存器 |
控制寄存器 | 控制FPU精度的16位寄存器 |
标记寄存器 | 描述8个数据寄存器的内容的16位寄存器 |
FIP寄存器 | 指向下一条FPU指令的48位FPU指令指针 |
FDP寄存器 | 指向内存中的数据的48位FPU数据指针 |
操作码寄存器 | 保存FPU处理的最后指令的11位寄存器 |
binutils包安装的所有程序见书34页。
as汇编器的命令行参数见书35页。
ld连接器的命令行参数见书38页。
gcc编译器的命令行参数见书40页。
gdb调试器的命令行参数见书43页。
objdump的命令行参数见书47页。
gprof简档器的命令行参数见书49页。
cpuid指令可用的不同输出选项见书57页。
gdb调试器的常用命令见书64页:
数据命令 | 描述 |
info registers | 显示所有寄存器的值 |
显示特定寄存器或者来自程序的变量的值 | |
x | 显示特定内存位置的内容 |
IA-32平台的数据声明伪指令:
命令 | 数据类型 |
.ascii | 文本字符串 |
.asciz | 以空字符结尾的文本字符串 |
.byte | 字节值 |
.double | 双精度浮点数 |
.float | 单精度浮点数 |
.int | 32位整数 |
.long | 32位整数(和.int相同) |
.octa | 128位整数 |
.quad | 64位整数 |
.short | 16位整数 |
.single | 单精度浮点数(和.float相同) |
定义静态符号:
.equ factor, 3
.equ LINUX_SYS_CALL, 0x80
bss段定义数据元素命令见书73页:
命令 | 描述 |
.comm | 声明未初始化的数据的通用内存区域 |
.lcomm | 声明未初始化的数据的本地通用内存区域 |
.fill 10000命令使汇编器自动地创建10000个数据元素。
mov指令有非常特殊94的规则,只有某些位置可以传送给其他位置,mov指令的源和目标操作数组合见书76页。
mov指令的源寄存器宽度和目标寄存器宽度必须相同。
记住在平坦内存模型中,所有内存地址都是使用32位数字表示的。
EFLAGS寄存器的作用:
ELFAGS位 | 名称 | 描述 |
CF | 进位(Carry)标志 | 数学表达式产生了进位或者借位 |
OF | 溢出(Overflow)标志 | 整数值过大或者过小 |
PF | 奇偶校验(Parity)标志 | 寄存器包含数学操作造成的错误数据 |
SF | 符号(Sign)标志 | 指出结果为正还是负 |
ZF | 零(Zero)标志 | 数学操作的结果为零 |
无符号条件传送指令和有符号条件传送指令列表见书84页。
指令 | 描述 |
XCHG | 在两个寄存器或者寄存器和内存位置之间交换值 |
BSWAP | 反转一个32位寄存器中的字节顺序 |
XADD | 交换两个值并且把总和存储在目标操作数中 |
CMPXCHG | 把一个值和一个外部值进行比较,并且交换它和另一个值 |
CMPXCHG8B | 比较两个64位值并且交换它们 |
使用xchg对内存位置进行操作时要小心。lock处理是非常耗费时间的,并且可能对程序性能有不良影响。
附加的PUSH和POP指令:
指令 | 描述 |
PUSHA/POPA | 压入或者弹出所有16位通用寄存器 |
PUSHAD/POPAD | 压入或者弹出所有32位通用寄存器 |
PUSHF/POPF | 压入或者弹出EFLAGS寄存器的低16位 |
PUSHFD/POPFD | 压入或者弹出EFLAGS寄存器的全部32位 |
POPF和POPFD指令的行为因处理器的操作模式而不同。当处理器运行在保护模式下的ring0(特权模式)下时,EFLAGS寄存器中的所有非保留标志都可以被修改,除VIP、VIF和VM标志之外。VIP和VIF标志被清零,VM标志不会被修改。
当处理器运行在保护模式的更高级别的ring(非特权模式)下时,会得到和ring0模式下的相同结果,并且不允许修改IOFL字段。
PUSH和POP不是把数据压入和弹出堆栈的唯一途径。也可以通过使用ESP寄存器作为内存指针,手工地把数据存放到堆栈中。
通常,会看到很多程序把ESP寄存器的值复制到EBP寄存器,而不是使用ESP寄存器本身。在汇编语言函数中经常使用EBP指针指向函数的工作堆栈空间的基址。访问存储在堆栈中的参数的指令相对于EBP值引用这些参数。
条件跳转指令列表见书107页。
条件跳转指令不支持分段内存模式下的远跳转。如果在分段内存模式下进行程序设计,就必须使用程序设计逻辑确定条件是否存在,然后实现无条件跳转转移到另一个段中的指令。
专门修改进位标志的指令(见书112页):
指令 | 描述 |
CLC | 清空进位标志(设置它为零) |
CMC | 对进位标志求反(把它改变为相反的值) |
STC | 设置进位标志(设置它为1) |
循环指令(见书112页):
指令 | 描述 |
LOOP | 循环直到ECX寄存器为零 |
LOOPE/LOOPZ | 循环直到ECX寄存器为零,或者没有设置ZF标志 |
LOOPNE/LOOPNZ | 循环直到ECX寄存器为零,或者设置了ZF标志 |
MMX寄存器被映射到FPU寄存器,所以使用MMX寄存器时要小心。记住,在使用任何MMX寄存器指令之前,都要把FPU寄存器中存储的所有数据保存到内存中。