AArch64教程第四章
本章,我们将看到一些指令,这些指令允许我们做一些计算。
算术指令
因为一个计算机就是一个精美的计算器(或者说一个小型的计算机),它做一些基本的算术。现在,我们只把它约束在整型操作。后面的章节,我们会看到我们这么做其他类型的计算。
加法和减法
我们能够用add
和sub
指令做加法和减法。这些指令有点灵活,因为可以以多种形式使用。
add Rdest, Rsource1, #immediate // Rdest ← Rsource1 + immediate
add Rdest, Rsource1, Rsource2 // Rdest ← Rsource1 + Rsource2
add Xdest, Xsource1, Xsource2, shiftop // Xdest ← Xsource1 + shiftop(Xsource2)
add Xdest, Xsource1, Xsource2, extop // Xdest ← Xsource1 + extop(Xsource2)
add Wdest, Wsource1, Wsource2, shiftop // Wdest ← Wsource1 + shiftop(Wsource2)
add Wdest, Wsource1, Wsource2, extop // Wdest ← Wsource1 + extop(Wsource2)
add Xdest, Xsource1, Wsource2, extop // Xdest ← Xsource1 + extop(Wsource2)
In the forms above Rx
means either Xx
or Wx
(but without mixing them in the same instruction), shiftop
and extop
are the shift and extension operands described in chapter 3. In this case, shiftop
does not include ROR
. All the forms shown for add
can be used for sub
as well.
上面的Rx
意味着要么Xx
或者Wx
(但是在同样的指令中没有混合),shiftop
和extop
是在第三章中描述的移位和扩展操作数。在这个例子中,shiftop
不会包括ROR
。所有的以add
展现的形式都能够用sub
替换。
乘法和除法
相对于加法和减法,乘法和除法是更难得操作。并且针对这些有不同的指令。
因为乘法的特性,乘以两个32/64的值可能会需要64/128的空间以满足全编码的计算结果。如果我们知道这不会发生(例如,值得结果能够在32/64位范围内表示)或者我们不关心我们使用mul
指令得结果。如果超过了位数,它们会被抛弃。
mul Rdest, Rsource1, Rsource2 // Rdest ← Rsource1 * Rsource2
// but be careful with overflow
如果我们关心超过的位数,那么我们就有一些指令要用了。对于32位的乘法,umull
和smull
能够被使用。后者被需要当在补码中做乘法,所以符号位需要被正确地控制。
umull Xdest, Wsource1, Wsource2 // Xdest ← Wsource1 * Wsource2
smull Xdest, Wsource1, Wsource2 // Xdest ← Wsource1 * Wsource2
// for two's complement numbers
// in Wsource1 and Wsource2
对于不那么通常的两个64寄存器的乘法,并且我们关系128位结果的高64位,那么我们能用umulh
和smulh
。对于此,我们需要2个64位的寄存器(在下面的例子中称为Xlower
和Xupper
)
mul Xlower, Xsource1, Xsource2 // Xlower ← Lower64Bits(Xsource1 * Xsource2)
smulh Xupper, Xsource1, Xsource2 // Xupper ← Upper64Bits(Xsource1 * Xsource2)
除法有点简单因为只有2个操作数是必须的:udiv
和sdiv
。同样,后面的整型数以补码方式编码。
udiv Rdest, Rsource1, Rsource2 // Rdest ← Rsource1 / Rsource2
sdiv Rdest, Rsource1, Rsource2 // Rdest ← Rsource1 / Rsource2
// when Rsource1, Rsource2 are
// in two's complement
上面两个指令会计算除法的商,结果向0舍入。
位指令
Bitwise instructions directly operate in the bits of the registers, without assuming any encoding in them.
位指令直接操作寄存器的位,而不用考虑它们的编码方式。
Instruction mvn
performs a bitwise not on its operand.
mvn
是取反指令
mvn Rdest, Rsource // Rdest ← ~Rsource
大部分位指令使用2个源寄存器。其基本的操作有and
,orr
和eor
(异或)。它们分别是位与,位或,和异或。
and Rdest, Rsource1, #immediate // Rdest ← Rsource1 & immediate
and Rdest, Rsource1, Rsource2 // Rdest ← Rsource1 & Rsource2
and Xdest, Xsource1, Xsource2, shiftop // Xdest ← Xsource1 & shiftop(Xsource2)
and Wdest, Wsource1, Wsource2, shiftop // Wdest ← Wsource1 & shiftop(Wsource2)
orr和eor的形式跟上面的差不多。对于位指令shiftop
包括ROR
。
有几个mvn
和orr
及eor
的组合版本,它们分别被称为bic
(位清空),orn
(或非)和eon
(异或非)。在这个例子中,第二个操作数是被应用非操作。它们的使用方式是有限制的。
orn Rdest, Rsource1, Rsource2 // Rdest ← Rsource1 | ~Rsource2
orn Xdest, Xsource1, Xsource2, shiftop // Xdest ← Xsource1 | ~shiftop(Xsource2)
orn Wdest, Wsource1, Wsource2, shiftop // Wdest ← Wsource1 | ~shiftop(Wsource2)
bic
和eno
也差不多。
针对更小范围的用途,aarch64有更多的指令,在这里,我们先忽略它们。
今天到此为止。