访问信息
一个x86-64的中央处理器单元包含一组16个存储64位值得通用目的寄存器.
有许多会生成小于八字节结果的指令, 对于寄存器中剩下的字节有两条规则:
- 生成1字节和2字节数字的指令会保持剩下的字节不变;
- 生成4字节数字的指令会把高位4个字节置为0(对于IA32的x86-64的扩展).
操作数指令符
操作数(Operand): 指示出一个操作中要使用的源数据值, 以及放置结果的目的位置.
各种不同的操作数的可能性被分为三种类型:
-
立即数(Immediate): 立即数的书写方是"$"后面跟一个用标准C表示法表示的常数, 比如$-123或$0x2F. 汇编器会自动选择最紧凑的方式进行数值编码;
-
寄存器(Register): 它表示某个寄存器的内容, 用引用来表示它的值. 比如寄存器寻址的%rax;
-
内存引用: 它会根据计算出来的地址(通常称为有效地址)访问某个内存位置.
寻址模式
允许不同形式的内存引用.
数据传输指令
下图是最简单的数据传送指令MOV类.
MOV类由四条指令组成:movb, movw, movl, movq. 主要区别在于它们操作的数据大小不同(1, 2, 4, 8)
注意, movabsq指令能够以任意64位立即数值作为源操作数, 并且只能以寄存器作为目的.
在将较小的源值复制到较大的目的时使用MOVZ或MOVS类中的指令, MOVZ类指令把目的中剩余的字节填充为0, 而MOVS类中的指令通过符号扩展来填充, 把源操作的最高位进行复制.
注意, cltq指令无操作数, 他总是以寄存器%eax作为源, %rax作为符号扩展结果为目的, 相比于movslq %eax, %rax更为紧凑.
理解数据传送如何改变目的寄存器
在上面的操作中需要注意的是, 第一行指令把寄存器%rax初始化, 而剩下的指令的源操作数值是立即数-1, 在不同的位下, 都形如FF…FF.