x86-64算术逻辑指令
目录
加载有效地址
一元和二元操作
移位操作
特殊的算术操作
加载有效地址
除了leaq,其他算数指令都有大小变种,leaq第一个操作数是一个地址,将这个地址复制到第二个操作数中,实际上该指令并不会引用内存,不会管这个地址处存的什么值,只是单纯将这个地址赋值给第二个操作数
可以看出leaq指令可用于加法和有限形式的乘法,对于简单表达式来说很有用。
一元和二元操作
一元操作只有一个操作数,这个操作数既是源又是目的,类似C语言++运算符。这个操作数可以是内存地址和寄存器。
二元操作第一个是源,第二个既是源又是目的,类似C语言+=运算符,第一个操作数可以是立即数、寄存器、内存位置,第二个操作数可以是寄存器和内存位置。当第二个操作数为内存位置时,处理器必须先从内存中读出值,执行操作,再把结果写回内存
移位操作
第一个操作数是移位量,第二个操作数是要移位的数。移位量可以是立即数,或者放在单字节寄存器%cl中(只允许这个特定的寄存器作为操作数)。一个自己的移位量可能很大,若超出了数据位数,则取数据位数-1为移位量。例如,%cl存了0xff,指令salb会移动7位,salw会移动15位,sall会移动31位,salq会移动63位。
两个左移效果完全一样,右移分为逻辑右移和算术右移。
特殊的算术操作
x86-64指令集对128位数提供了有限的支持。 将16字节的数称作八字。上图描述了支持产生两个64位数字的全128位乘积和整数除法的指令。
可以看到上面的imulq只有一个操作数,要把它与两个操作数的imulq指令区分开来,汇编器会根据操作数的不同分辨出两条指令。
imulq指令和mulq指令要求一个参数存放在%rax中,另一个作为源给出,然后乘积存放在%rdx(高64位)和%rax(低64位)中。
前面没有提到除法指令和取模指令,这些操作是由单操作数除法实现的。
有符号除法idivq将寄存器%rdx(高64位)和%rax(低64位)中的128位数作为被除数,除数作为指令的操作数给出。商存储在%rax,余数存储在%rdx。
对于大多数64位除法来说,被除数常常是64位的值,这个值应被存放在%rax(低64位)中,%rdx的值应该被设为全0(无符号除法)或全符号位(有符号除法)。后面这个操作可以由clto指令完成。这个指令没有操作数,读出%rax的符号位并将其复制到%rdx的所有位。
无符号除法通常用divq指令,%rdx通常会被设为0.