3.5 算术和逻辑操作
3.5.1 加载有效地址
加载有效地址(load effective address
)指令 leaq
实际上是 movq
指令的变形。它的指令形式是从内存读数据到寄存器,但实际上它根本就没有引用内存,而是将有效地址写入到目的操作数。
3.5.2 一元和二元操作
e.g
.:
一元操作:
incq (%rsp)
二元操作:
subq %rax, %rdx
3.5.3 移位操作
左移指令有两个名字: SAL 和 SHL(二者效果一样,都是将右边补上 0 )。右移指令也有两个: SAR 执行算术右移(左边填上符号位), 而 SHR执行逻辑移位(填上 0 )。
3.5.4 讨论
大多数指令既可以用于无符号运算,也可以用于补码运算。只有右移操作要求区分有符号和无符号数。
示例:
tips:
xorq %rdx, %rdx
对 %rdx 求 0
任何更新低位4字节的指令都会把高位字节设置为0
xorl %edx, %edx
( 字节)
等价于movl $0, %edx
(5字节)
3.5.5 特殊的算术操作
imulq
指令有两种不同形式。其中一种是一个“双操作数”乘法指令。它从两个64
位操作数产生一个64
位乘积,实现了2.3.4
和2.3.5
节中的操作
和
(将乘积截取到64
位时,无符号乘法和补码乘法的位级行为是一样的。)。
另一种“单操作数”乘法指令(包含无符号乘法(mulq
)和补码乘法(imulq
)。
这两条指令都要求一个参数必须在寄存器 %rax
中,而另一个作为指令的源操作数给出。乘积存放在寄存器 %rdx
(高64
位)和 %rax
(低64
位)中。
示例:
除法和取模操作。有符号除法指令 idivl
将寄存器 %rdx
(高64
位)和%rax
(低64
位)中的 128
位数作为除数,而除数作为指令的操作数给猪。指令将商存储在寄存器 %rax
中,将余数存储在寄存器 %rdx
中(取模运算结果)。
特殊点:对于64
位除数来说,这个值通常存放在 %rax
中, %rdx
的位一个设置全为 0
(无符号运算)或者 %rax
的符号位(有符号运算)(可以用一个无操作数指令 cqto
来完成,该指令隐含读出 %rax
的符号位并将结果复制到 %rdx
的所有位)。
示例:
qp
需要先保存到另一个寄存器,除法操作占用%rdx
,cqto R[%rdx]:R[%rax] <-- 符号拓展 R[%rax]
,商在%rax
中,余数在%rdx
中。
无符号除法使用 divq
,通常%rdx
事先置零。