2

誰か私に次のことを説明してもらえますか?

0x0110 003F以下は、乗算命令を使用せずに定数のR1倍を乗算する最小長のARM命令シーケンスです。

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

理由はわかりませんが0x110X3F0x0110 003F

ARMアーキテクチャまたはhexに精通している人は、この手順を説明してくれますか?なぜRSBが使われるのですか?

4

3 に答える 3

5

数学は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フォームに命令を保存する必要がありました。

于 2012-08-22T03:57:20.130 に答える
1

擬似コード(および小数)の行は次のとおりです。

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

...そして1782585516進数で110003F

これらの数値が使用される理由に関する質問に答えるために、それは農民の乗算とシフトと加算への分解に関連します。の定数値110003Fは実際には次のとおりです。

(2 4 + 1 )* 2 20 + 2 6-1

于 2012-08-22T03:50:26.233 に答える
0

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 << 6r1 * 64、なので、2行目は、、r3 = r1 * 64 - r1またはr3 = r1*63です。

同じパターンに従って、最後の行はr3 = r3 + r2 * 1048576、を示します。これは、前の行の値を代入すると、ですr3 = r1*63 + r1*17*1048576r3 = 17825855 * r1これは、、またはに簡略化されr3 = 0x0110003f * r1ます。

于 2012-08-22T03:56:12.543 に答える