數學無關與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。在二進制(基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
爲什麼反向減法使用,是因爲執行
原因10
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表單來保存指令。