AT&T汇编——算术和逻辑操作

算术和逻辑操作

加载有效地址

指令效果描述
leaq S,D D ← & S D \leftarrow \&S D&S加载有效地址

加载有效地址指令leaq实际上是movq指令的变形。
它的指令形式是从内存读取数据到寄存器,但实际上它根本没有引用内存。
它的第一个操作数看上去是一个内存引用,但该指令并不是从指定的位置读入数据,而是将有效地址写入到目的操作数。
这条指令可以为后续的内存引用操作产生指针。
另外,它还可以简洁地描述普通的算术操作。
例如,如果寄存器%rdx的值为x,那么指令leaq 7(%rdx, %rdx, 4), %rax %rax 将设置寄存器%rax的值为5x+7。
编译器经常发现leaq的一些灵活用法,根本就与有效地址计算无关。
目的操作数必须是一个寄存器。

一元操作

指令效果描述
INC D D ← D + 1 D \leftarrow D+1 DD+1加1
DEC D D ← D − 1 D \leftarrow D - 1 DD1减1
NEG D D ← − D D \leftarrow -D DD取负
NOT D D ← − D D \leftarrow -D DD取补

只有一个操作数,既是源又是目的。这个操作数可以是一个寄存器,也可以是一个内存位置。
上的指令是对一类指令的概括,每一类指令都可以根据数据类型的大小来进行扩展,例如,incb、incw、incl和incq。

二元操作

指令效果描述
ADD S,D D ← D + S D \leftarrow D + S DD+S
SUB S,D D ← D − S D \leftarrow D - S DDS
IMUL S,D D ← D ∗ S D \leftarrow D * S DDS
XOR S,D D ← D ⨁ S D \leftarrow D \bigoplus S DDS异或
OR S,D D ← D ⋁ S D \leftarrow D\bigvee S DDS
AND S,D D ← D ⋀ S D \leftarrow D \bigwedge S DDS

第二个操作数,既是目的又是源。
不过,要注意,源操作数是第一个,目的操作数是第二个,对于不可交换的操作来说,这看上去很奇特。
第一个操作数可以是立即数、寄存器或者内存位置。
第二个操作数可以寄存器或者内存位置。
注意,当第二个操作数为内存地址时,处理器必须从内存读出值,执行操作,再把结果写回内存。
上述指令同样也会根据类型的不同进行扩展。

移位操作

指令效果描述
SAL k,D D ← D ≪ k D \leftarrow D \ll k DDk左移
SHL k,D D ← D ≪ k D \leftarrow D \ll k DDk左移(等同于SAL)
SAR k,D D ← D ≫ k D \leftarrow D \gg k DDk算术右移
SHR k,D D ← D ≫ k D \leftarrow D \gg k DDk逻辑右移

移位操作,先给出移位量,然后第二项给出的是要移位的数。
可以进行算术和逻辑右移。
移位量可以是一个立即数,或者放在单字节寄存器%cl中。这些指令很特别,因为只允许以这个特定的寄存器作为操作数。
原则上来说,1个字节的移位量使得移位量的编码范围可以达到 2 8 − 1 = 255 2^8-1=255 281=255
x86-64中,移位操作对 w w w位长的数据值进行操作,移位量是由%cl寄存器的低 m m m决定的,这里 2 m = w 2^m=w 2m=w。高位被忽略。
左移指令有两个名字:SAL和SHL。两者的效果是一样的,都是将右边填上0。
右移指令不同,SAR执行算术移位(填上符号位),而SHR执行逻辑移位(填上0)。
移位的目的操作数可以是一个寄存器或是一个内存位置。

特殊的算术操作

当两个64位有符号或无符号整数相乘得到的乘积需要128位来表示时,这就是特殊的算术操作的使用场景。
x86-64指令集对128位(16字节)数的操作提供了有限的支持。
延续字(2字节)、双字(4字节)和四字(8字节)的命名惯例,Intel把16字节的数称为八字(oct number)。
下表列出了支持产生两个64位数字的全128位乘积以及整数除法的指令。

指令效果描述
i m u l q S imulq \quad S imulqS R [ % r d x ] : R [ % r a x ] ← S × R [ % r a x ] R[\%rdx]: R[\%rax] \leftarrow S \times R[\%rax] R[%rdx]:R[%rax]S×R[%rax]有符号全乘法
m u l q S mulq \quad S mulqS R [ % r a x ] : R [ % r a x ] ← S × R [ % r a x ] R[\%rax]: R[\%rax] \leftarrow S \times R[\%rax] R[%rax]:R[%rax]S×R[%rax]无符号全乘法
c l t o clto clto R [ % r d x ] : R [ % r a x ] ← 符 号 扩 展 ( R [ % r a x ] ) R[\%rdx]:R[\%rax] \leftarrow 符号扩展(R[\%rax]) R[%rdx]:R[%rax](R[%rax])转换为8字
i d i v q S idivq \quad S idivqS R [ % r d x ] ← R [ % r d x ] : R [ % r a x ] m o d S R[\%rdx] \leftarrow R[\%rdx]: R[\%rax] modS R[%rdx]R[%rdx]:R[%rax]modS
R [ % r d x ] ← R [ % r d x ] : R [ % r a x ] ÷ S R[\%rdx]\leftarrow R[\%rdx]:R[\%rax] \div S R[%rdx]R[%rdx]:R[%rax]÷S
有符号除法
d i v q S divq \quad S divqS R [ % r d x ] ← R [ % r d x ] : R [ % r a x ] m o d S R[\%rdx] \leftarrow R[\%rdx]:R[\%rax] mod S R[%rdx]R[%rdx]:R[%rax]modS
R [ % r d x ] ← R [ % r d x ] : R [ % r a x ] ÷ S R[\%rdx] \leftarrow R[\%rdx]:R[\%rax] \div S R[%rdx]R[%rdx]:R[%rax]÷S
无符号除法

关于imulq指令有两种不同的形式。
其中,一种就是前面讲到的普通的四字乘法指令,该指令是一个双操作数的指令,它从两个64位操作数产生一个64位乘积。
另一种,就是这里提到的两条单操作数乘法指令,以计算两个64位值的全128位乘积——一个无符号数乘法,另一个是补码乘法。
这两条指令都要求一个操作数必须在寄存器 % r a x \%rax %rax中,而另一个作为指令的源操作数给出。
然后乘积放在寄存器 % r a x \%rax %rax(高64位)和 % r a x \%rax %rax(低64位)中。
虽然imulq这个名字可以用于两类不同的乘法操作,但是汇编能够通过计算操作数的数目,分辨出想用哪条指令。

有符号除法指令 i d i v q idivq idivq将寄存器 % r d x \%rdx %rdx(高64位)和 % r a x \%rax %rax(低64位)中的128位数作为被除数,而除数作为指令的操作数给出。
将指令的商存储在寄存器 % r a x \%rax %rax中,将余数存储在寄存器 % r d x \%rdx %rdx中。
对于大多数64位除法应用来说,除数也常常是一个64位的值。
这个值应该存放在 % r a x \%rax %rax中, % r d x \%rdx %rdx的位应该设置为全0(无符号运算)或者 % r a x \%rax %rax的符号为(有符号运算)。
后面这个操作可以由指令 c q t o cqto cqto来完成。
这条指令不需要操作数——它隐含读出 % r a x \%rax %rax的符号位,并将它复制到 % r d x \%rdx %rdx的所有位。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值