数学与ARM无关...
ADD r2,r1,r1, LSL #4 r2 = r1 + (r1 << 4);
RSB r3,r1,r1, LSL #6 r3 = (r1 << 6) - r1;
ADD r3,r3,r2, LSL #20 r3 = r3 + (r2 << 20);
还记得小学的乘法吗?
123
x 12
=====
246
+123
=====
1476
现在关于二进制乘法的真正酷的事情是,您可以将每列的数字乘以 1 或 0(2 的幂)。在个数列上方的十进制数学中,以 (10) 为底的 0 次方,其中包含 2。在二进制(base 2)中,我们不会有。对于十列(以 1 的幂为底),就像我们将在二进制中看到的那样,取顶部的数字并将其乘以以 1 为底的幂(左移一位)并将其添加/累加到结果中。
因此,如果我想在基数 2(二进制)中将某个值乘以 0b1011,我设置了位 3、1 和 0,
result = (x<<3) + (x<<1) + (x<<0);
乘以 0x0110003F,我们可以对 8 位中的每一个进行加法运算
result = (r1<<24)+(r1<<20)+(r1<<5)...
但我们可以使用更基础的数学。
rx * 0x3F
0x3F = 0x40 -1
rx * 0x3F = rx * (0x40 - 1)
distribute
rx * 0x3F = (rx * 0x40) - (rx * 1)
rx * 0x3F = (rx * 0x40) - rx
we know from the comments above that
rx * 0x40 = rx << 6
rx * 0x3F = (rx << 6) - rx
现在
ADD r2,r1,r1,lsl 4 r2 = r1 + (r1 << 4)
r2 = r1 + (r1 << 4)
r2 = r1 + (r1 * 0x10)
r2 = (r1 * 1) + (r1 * 0x10)
r2 = r1 * (1 + 0x10)
r2 = r1 * 0x11
所以
r3 = r1 * 0x3F
r2 = r1 * 0x11
最后一步是
result = r3 + (r2<<20)
result = (r1 * 0x3F) + ((r1*0x11)<<20)
result = (r1 * 0x3F) + ((r1*0x11)*0x100000)
result = (r1 * 0x3F) + (r1*0x1100000)
result = r1 * (0x3f + 0x1100000)
result = r1 * 0x110003F
之所以使用反向减法是因为要执行
r3 = (r1 << 6) - r1
使用 ARM 指令可以通过以下几种方式完成:
mov r3,r1,lsl 6 r3 = (r1 << 6)
sub r3,r3,r1 r3 = r3 - r1
或者
rsb r3,r1,r1,lsl 6 r3 = (r1 << 6) - r1
rsb 只是意味着反向减法,一个正常的减法
sub ra,rb,rc means ra = rb - rc
反向减法意味着反转操作数的顺序
rsb ra,rb,rc means ra = rc - rb
要对像这样的三种寄存器格式的 arm 上的操作数进行移位,它必须是最后一个操作数,所以如果你想移位减法的左操作数,那么使用 rsb。
sub ra,rb,rc,lsl x means ra = rb - (rc << x)
rsb ra,rb,rc,lsl x means ra = (rc << x) - rb
我们想要 rsb 表单来保存指令。