[英]ARM assembly hex multiplication
谁能向我解释以下内容?
以下是最小长度的ARM指令序列,该序列将R1乘以常数0x0110 003F
而不使用乘法指令
ADD r2, r1, r1, LSL #4 //r2 = 0x11 * r1
RSB r3, r1, r1, LSL #6 //r3 = 0x3F * r1
ADD r3, r3, r2, LSL #20 //r3 = 0x0110 003F * r1
我不确定为什么使用0x11
和0X3F
来获取0x0110 003F
熟悉ARM体系结构或十六进制的任何人都可以为我解释此过程吗? 为什么使用RSB?
数学与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的幂)。 在“ 1”列上方的十进制数学中,以0为底的(10)为2。 在二进制(基数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
要对三种寄存器格式在臂上操作数进行移位,它必须是最后一个操作数,因此,如果要让减法运算符的左操作数移位,请使用rsb。
sub ra,rb,rc,lsl x means ra = rb - (rc << x)
rsb ra,rb,rc,lsl x means ra = (rc << x) - rb
我们希望rsb表单保存指令。
这是您的伪代码行(和十进制):
r2 = r1 + (r1 <<4) == r1 * 16 + r1 == r1 * 17
r3 = r1 << 6 - r1 = r1 * 64 - r1 = r1 * 63
r3 = r3 + r2 << 20 = r3 + r2 * 1048576
将第1行和第2行替换为3:
r3 = (r1 * 63) + 1048576 * (17 * r1) = r1 * (63 + 17825792) = r1 * 17825855
...和17825855
十六进制为110003F
!
为了回答有关为什么使用这些数字的问题,它将与农民乘法以及分解为移位和加法有关。 您的恒定值110003F
实际上是这样的:
(2 4 +1)* 2 20 +1 2 6-1
如果您熟悉C,这里是逐行转换(使用变量而不是寄存器):
r2 = r1 + (r1 << 4);
r3 = (r1 << 6) - r1;
r3 = r3 + (r2 << 20);
回想一下r1 << 4
与r1 * 16
相同,因此第一行说r2 = r1 + r1*16
或r2 = r1*17
。
同样, r1 << 6
是r1 * 64
,因此第二行显示r3 = r1 * 64 - r1
或r3 = r1*63
。
遵循相同的模式,最后一行说r3 = r3 + r2 * 1048576
,用前几行的值替换为r3 = r1*63 + r1*17*1048576
。 简化为r3 = 17825855 * r1
,或r3 = 0x0110003f * r1
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.