数学は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の列の上の10進数の計算では、0の累乗の底(10)に2が含まれています。バイナリ(基数2)ではそれはありません。2進数で表示されるような10の列(1の累乗の基数)の場合、一番上の数値を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
このような3つのレジスタ形式で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フォームに命令を保存する必要がありました。