2016-10-03 13 views
1

レジスタ$ t0には整数が格納されています。たとえば、整数1100を格納するとします。この値のバイナリ表現は0000010001001100です。もちろん、32ビットレジスタの場合は32ビットまで拡張できますが、それは簡単に実行できます。レジスタ値の各ビットを介したアセンブリループ

私は、レジスタ値の各ビットを反復し、1または0であるかどうかを調べるアセンブリでループを実装しようとしています。

多分私はレジスタの性質を誤解しています。レジスタには32ビットの数値が格納されていると私は理解しています。これは、各ビットが特定のアドレスに格納されていることを意味しますか?

私はレジスタのシフトを使用してビットをチェックしようとしましたが、失敗しました。私もlbコマンドを調べましたが、これはビットではなくバイトをロードします。だから1人は何をするだろうか?

答えて

2

いずれのプロセッサでも、レジスタのビット数をカウントするループを設定します。この場合は32です。ループを通過するたびに、関心のあるレジスタを1に設定し、結果をアキュムレータに加算します。最後にレジスタをシフトします。これにより、設定されたビット数が得られます。

正確な手順は、プロセッサによって異なります。通常はラベルをループし、カウンタを減らしてから、branch_not_equal_toゼロ(BNZ、BNEQ0のようなもの)のような名前の命令を実行します。とAND、ANDI(と即時)のような名前がつけられます。 ADDはADD、ADC(キャリー付き加算)です。シフトはASR(算術シフト右)LSR(論理シフト右)のようなものになります。シフトを1つだけ行うと1にする必要があります。しかし、すべてのプロセッサでは基本的にこのようにレジスタビットを読み出すことができます。

+0

@Malcom McLean ANDは何をしますか?編集:質問を編集しました。私は何を尋ねるつもりだったと私は謝罪を追加しません – user3794422

+0

2つの数字を一緒に追加します。通常は2つのレジスタです。 –

+0

@Malcom McLean私は私のコメントを編集してください – user3794422

3

いくつかの基本:

ほとんど(すべて?)シフト命令はキャリーフラグにビットをシフトアウト

ほとんど(全て?)のCPUは、キャリーフラグのセット上の場所にジャンプし、分岐命令を持っています

これを組み合わせて、次の操作を行うことができます:

load register1,< the value to be tested > 
load register2, 0 

Lrepeat: 
    compare register1 with 0 
    jump if zero Lexit 

    shift right register1 
    jump no carry Lskip 
    increase register2 
Lskip: 
    jump Lrepeat 

Lexit:      ; when you end up here, your register2 
          ; holds the count of bit register1 had set 

まだ行うことができますいくつかの最適化:

Lrepeat: 
    compare register1 with 0 
    jump if zero Lexit 
    shift right register1 
    jump no carry Lskip  <-- note: here you jump ... 
    increase register2 
Lskip: 
    jump Lrepeat    <-- ... to jump again! 
Lexit: 

=====> 

Lrepeat: 
    compare register1 with 0 
    jump if zero Lexit 
    shift right register1 
    jump no carry Lrepeat  <-- so you can optimize it this way 
    increase register2 
Lskip: 
    jump Lrepeat    
Lexit: 

いくつかのCPUには、「追加キャリー」インストルメントがあります( )。 6502:

ADC register,value  ; register = register + value + Carry flag 

これはあなたがする必要はありません各ループ

shift right register1 
    add with carry register2,0 ; may look weird, but this adds a 
           ; 1 if the carry is set, which is 
           ; exactly what we want here 
    jump Lrepeat 

ノートをレジスタ2 0(プラスもちろんキャリー)を追加することにより、ブランチ(条件ジャンプ)を回避するために使用することができレジスタのサイズを知っている!レジスタが1になるまでループするだけで、多くの時間を節約できます。あなたの値が次のようなものなら0000 0000 0000 0000 0000 0001 1001

+0

私はMIPSを使用しています。これはキャリーフラグを持っていないようですか?右?あるいは私は何かを逃している。 また、ループLrepeatの下で "compare register1 to 0"と言う。レジスタ1に何らかの値がある場合(たとえば、1450をバイナリに変換した場合)、レジスタは0と比較してどのような値になりますか?私はこれのポイントは1を見つけることであると仮定しますが、それはどのように機能しますか? – user3794422

+0

ああ、私はあなたが何かを混ぜると思う。私は十分にはっきりしていなかった。 "ゼロの場合ジャンプ" < - ここではゼロFLAGがチェックされます。 Lrepeatは、値の中のすべての1ビットがカウントされているかどうかを調べる際に使用されるラベルです(シフトアウトされます)。これが当てはまると、レジスタには0が含まれ、ループが停止する可能性があります。そのため、値は0と比較されます – Tommylee2k

+0

MIPSにフラグがありません。これには、0より大きいかブランチかを比較するための 'BEQ reg1、reg2、target'、または' BGEZ reg、target'のような命令があります。 http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html。ですから、あなたは 'andi $ t0、$ t1、0x1'を使って$ t0 = $ t1の下位ビットを設定すると思います。 (アーキテクチャ上のゼロレジスタがあるので、 'beq $ t0、$ 0、low_bit_zero'を実行できます) –

0

反復したいレジスタをR0とします。例えば、最下位ビットはR0= 1011 0101です。

2)2番目にクリアされたレジスタR1=0000 0001を使用します。R0

3)ANDR1と右シフトR0(SO次の反復チェックR0の次のビット)。

4)うR3 1における1つのIFAND演算結果によってインクリメント(つまり、あなたが)R0 1に実行することを第3のレジスタです。 ELSE、再度ループしてR0の次のビットをチェックします。

デクリメントするループカウンタを使用して、32ビット全体または任意の長さを繰り返し処理できます。

関連する問題