私はマイクロプロセッサクラスに所属しており、FreescaleCodeWarriorのアセンブリ言語を使用して68HCS12マイクロコントローラをプログラムしています。今週の割り当てはバイトを反転することなので、バイトが00000001の場合、出力は10000000、つまり00101011から11010100になります。アセンブリ言語を使用する必要があり、回転とシフトを使用できると言われました(ただし、これに限定されません! )このタスクを実行します。どこから始めればいいのか、本当に迷っています。
9 に答える
ヒント:シフトを実行すると、1ビットがシフトアウトされ、ゼロ(おそらく)がシフトインされます。そのシフトアウトビットはどこに移動しますか?これをデスティネーションレジスタまたはメモリアドレスのもう一方の端にシフトインする必要があります。
25年前は、アセンブラなしでZ80マシンコードでこれを実行できたと確信しています:)
2つのレジスタをビットのスタックと見なします。一度に1ビットずつ移動するとどうなりますか?
256バイトの余分なコードサイズを節約できる場合は、ルックアップテーブルが68HCS12のバイトを逆にする最も効率的な方法です。しかし、これはあなたのインストラクターが期待していることではないと私は確信しています。
「通常の」ソリューションの場合、データビットを個別に検討します。回転とシフトにより、ビットを移動できます。最初の解決策として、8ビットを分離し(ビット単位の「および」演算を使用)、それらを宛先位置に移動し(シフト、回転...)、次にそれらを再度結合します(ビット単位の「または」演算を使用)。これは最も効率的または最も単純な実装ではありませんが、最初に正しい結果を得ることに集中する必要があります-最適化は待つことができます。
右シフトを実行すると、最下位ビットがキャリーフラグに入ります。
ローテーションを実行すると、キャリーフラグを使用して、結果の空のビットが埋められます(ROLの場合はLSB、RORの場合はMSB)。
まず最初に、必要なことを実行するためのアルゴリズムを作成します。擬似コードまたはCまたは平易な英語または図またはあなたが快適なものとしてそれを表現してください。この概念的なハードルをクリアすると、実際の実装は非常に簡単になります。
CPUには、おそらくキャリーフラグを追加ビットとして含めて、レジスタをシフトおよび/またはローテーションできる命令があります。これらの手順は非常に役立ちます。
たとえば、すべてのバイト番号がある場合、最も簡単な方法は次のとおりです。
mov al, 10101110
mov ecx, 8
ecxforループに8を入れます
mov ebx, 0
blでは、結果が得られ、ebxが作成されますが、何がより良くなるかを確認するだけです。
loop1:
sal al, 1;
キャリーフラグでは、左から最後のビットがあります
rcr bl, 1;
今、あなたはあなたが持っているものをblに追加します
loop loop1
それだけです
コメントでしたが、WTHだと思いました!
256バイトのテーブルのスペースを節約するために、一度に4ビット(ニブル)の値を含む16バイトのテーブルを作成できます。その場合、アルゴリズムは次のようになります。
revval=(revdigit[inval&0x0f]<<4)|
revdigit[inval>>4];
私が教授だったとしたら、確かに、一方のシフトがインデックス作成にあり、もう一方のシフトが外部にある2つの部分が欲しいです。
また、大学用にこのビットリバースをプログラムする必要がありました(8ビット用)。これが私がした方法です:
MOV AL, 10001011B ;set the value to test
MOV CL, 7
MOV DH, 1
MOV DL, 0
loop1: PUSH AX
AND AL, DH
PUSH CX
MOV CL, DL
SHR AL, CL
POP CX
MOV BH, AL
SHL BH,CL
OR CH,BH
DEC CL
INC DL
SHL DH, 1
POP AX
CMP DL, 8
JE END
JMP LOOP1
END:
コメントしなかったので、次のように機能します。DHは、1
初めてのようにバイト内を移動するもの00000001
です。2回目00000010
など。AND
あなたがALであなたが得る0
か何かのようなものを作るとき、100
または10000
あなたはそれをまたはとして得るためにそれを右にシフトしなければなりませ0
ん1
。7
次に、それをBHに入れて、バイト0
、6
バイトなどの目的の位置に移動し1
ます。次にOR
、最終結果とINC
必要DEC
なものについて説明します。条件付きジャンプを忘れずAX
に、次のループにポップしてください:)
結果はCHになります。
次のコードは、回転とシフトを利用しています。Intel x86構文を使用しています。右側の説明を参照してください:
mov cx, 8 ; we will reverse the 8 bits contained in one byte
loop: ; while loop
ror di ; rotate `di` (containing value of the first argument of callee function) to the Right in a non-destructive manner
adc ax, ax ; shift `ax` left and add the carry, the carry is equal to 1 if one bit was rotated from 0b1 to MSB from previous operation
dec cx ; Decrement cx
jnz short loop ; Jump if cx register Not equal to Zero else end loop and return ax
subの代わりにdec命令を使用します。これは、subが3バイトかかるのに対し、1バイトしかかからないためです。その上、コンパイラは常にdecoversubを選択することで最適化するようです。
編集:(3バイト)が(2バイト)の後に(2バイト)が続くrcl ax
のと同等の 効率が低いことにも注意してください。以下のコメントを参照してください。彼の洞察を提供してくれたPeterCordesに感謝します。adc ax, 0
shl ax