2017-01-05 8 views
0

私はARMには新しく、レジスタの値と既知の16進値の選択を比較しようとしています。コードは次のようになりますので、現時点では私は、個々のCMP命令を使用してこれをやっている:ARM THUMB2関数はいくつかの値と比較する

;stuff 

CMP r2, #0x41 

CMP r2, #0x45 

CMP r2, #0x49 

etc... 

明らかに、これはしばらくかなり厄介取得し、私はR2への値を比較する方法がなければならないと思っています一度にいくつかの16進値が得られます。

初心者向けの質問、事前のおかげで質問します。

+0

配列で比較したい値を持っていて、それをループします –

+0

比較のバイナリ検索のようなツリーができます。 – EOF

+0

それはアセンブリ言語の性質のようなものですが、RISC、おそらくCISCではなく、多くのことを一度に命令と比較することはありませんが、例外を表示する可能性があります。あなたは多分比較の数を減らすことができますが、親は1対多数の命令を比較しません。 –

答えて

0

通常、有効な値の範囲を調べます。

  1. 値が範囲内にあることを確認します。
  2. レジスタから最小値を引きます。
  3. 配列インデックスとして変更された値を使用します。配列は値キーを持つか、単にyes/noにすることができます。

ステップ2,3は、範囲内の一部の値が有効ではなく、配列がかなり密にパックされている必要がある場合にのみ必要です。これは2桁の16進数の場合です。

# Range check (step 1) 
    cmp r2, #hi_val 
    bhi out_of_range 
    cmp r2, #low_val   ; optimized version is subs r2, r2, #low_val 
    blo out_of_range 

    # Adjust value (step 2) 
    sub r2, r2, #low_val  ; removed in optimized version. 

    # Get check from array (step 3) 
    adr r0, key_array 
    ldrb r0, [r0, r2] ; base of array + adjusted value. 
    bx lr   ; return w. result in r0. 

# Handle not in range. 
out_of_range: 
    mov r0, #-1 
    bx lr   ; use 0xffffffff for out of range. 

# This is a constant array included with the code. 
key_array: 
    .byte 1, 1, 0, 1, 1, 1, 0, 0, 1, 1 # etc. 

もちろん、あなたkey_arrayはあなたのユースケースで有効になるように変更する必要があります。条件付きコードは、符号付きおよび符号なしの値に対してわずかに変更されます。

key_arrayがすべてバイナリケースの場合は、ステップ2と3はちょうどreturn 1;です。 low_valがゼロの場合、減算する必要はありません(または低範囲チェックを行う)。 key_arrayのサイズはhi_val - low_val + 1である必要があります。また、範囲チェックロジックが変更される可能性があります。

このメカニズムは、ispunctなどの多くの 'ctype'関数で使用されますが、バイトに最大8個の値を格納し、ビットマスクを使用して興味のあるものを取得することもできます。 'C'を実行し、コンパイラを使用します。レジスタは1つしか使用できません(R0はEABI互換機能です)が、エラー処理も混在しています。

関連する問題