2017-05-13 6 views
2

私の教授は議会が私のコースのほんの一部ですので、我々は技術的に多くのにもらっていない モジュラス

int k = 0, S = 0; 
for (k=0; k<100; k++) 
{ 
if (k%2 == 0) 
S += k; 
else 
S -= k; 
} 

アセンブリコードには、このCコードを変換するために私に割り当てを与えました部品。私が持っている唯一の問題は、モジュラス部分にあります。私たちは分裂をしただけで、モジュラスの使い方を学んだことはありませんでした。 これは私の知る限り、私の仕事に

MOV CX, 0; counter 
MOV AX, 0; This represents S, we haven't learned how to declare variables in assembly, so we use registers instead) 
Loop1: 
     CMP [Haven't done the modulus condition] 
     JE iftrue 
     JNE ifwrong 
iftrue: 
     ADD AX, CX 
     INC CX 
     CMP CX, 99 
     JL Loop1 
ifwrong: 
     SUB AX, CX 
     INC CX 
     CMP CX, 99 
     JL Loop1 

を持っているとして、あなたは私が第一条件に記入助けることはできますか?比較でモジュラスを使用し、残りが0かどうかをチェックするにはどうすればよいですか?

P.S.私はループ内で条件を行う方法も学んでいないので、iftrue/ifwrongの部分は私の最後の即興の即興です。効率的かどうかはわかりません。その部分をより良い形で行うことができますか?

+0

問題の核心は、 '%2'は'&1'と言うだけでは効率が悪いことです。 =) –

+1

あなたは本当に指示参照を見てください。残りの部分がレジスタに格納されていることがわかります。残りはモジュラスである。 –

+0

ありがとう、しかし私が言ったように、アセンブリは私のコースのほんの一部です。私たちはわずかに3-4のレジスタについてしか教えていません。残りの部分を直接使用することは、私の教授が私のクラスで教えてくれたものではありません。もし私がそれを使うならば、おそらくそれを間違ったものとしてマークするでしょう。ありがたいことに、これは約%2なので、偶数か奇数かを調べるだけです。 Mikeの答えは、私がこの問題に対する許容可能なアプローチを見つけ出すのを助けました。 – Axel1212

答えて

5

教授は、一般に、あなたがまだ学習していないものを含む課題を与えません。外部の観察者(この質問を読んでいる人など)にとって、ほとんどの場合、注意を払っていないか、説明されていることがモジュラス操作を達成する方法であることを認識していないということです。

x86アセンブリのモジュラスは、2つの数値を除算することによって得ることができます。ディビジョンをいくつかのレジスタに入れ、いくつかの命令で除数を実行し、命令が実行された後にいくつかのレジスタが商を受け取り、別のレジスタが残りを受け取ります。しかし、それは無関係です。なぜならあなたはおそらく分割操作を学んでいないでしょうし、それは大丈夫です。なぜなら、私たちはではないからを使用するためです。

x86アセンブリ(およびそれに関する他のアセンブリ)では、除算操作を使用せずに、の除数の残りを2の累乗で非常に簡単に計算できます。 2は2の累乗です(2の1乗)。

実際には、2の場合はさらに単純になります。2で除算の残りの部分が1つまたは0の2つの可能な結果しかありません。

バイナリの数字は次のようになります。0011101010左端のビットが最上位ビットで、右端のビットが最下位ビットです。そして、数字の最下位ビットは、その数を2で割ったときに受け取る残りの部分を常に表すことを表す数値の二項体系の基本的な特性です。 (小数点システムの場合と同様に、右端の桁は、その数値を10で割った場合に残る剰余を表します)。

したがって、最下位ビットを番号から分離するだけです。これは0または1になり、残りの数字を2で割ったものになります。

"これを達成するための正確な方法は、学生には練習として残されています。

(それを試してみると、あなたがそれを行うことができない場合は、別のstackoverflowの質問を投稿してください。)

JE/JNE部分についてはCXが終わるとき未満99 JL Loop1するので、それは、実際に間違っています命令はifwrong:ラベルに貼り付けられます。これはあなたが望むものではありません。あなたは正確に、ADD AX, CXSUB AX, CXをしたくないあなたはとSUB AX, MMをしたい、MMはCX弾性率2であり、そしてそのあなたが方法を考え出すの過程にまだある

JE iftrue 
ifwrong: ;unnecessary label, for illustration purposes only 
    SUB AX, CX 
    JMP after 
iftrue: 
    ADD AX, CX 
    JMP after ;unnecessary instruction, for illustration purposes only. 
after: 
    INC CX 
    CMP CX, 99 
    JL Loop1 

注:次のようにあなたはそれを書き換える必要があります計算する。

CMP CX, 99に続いてJL Loop1が正しいかどうかを保証していないことに注意してください。あなたはそれについて尋ねたことはありませんが、後で遭遇するでしょう。

+0

ありがとうございました。私はJMPを認識していますが、クラスで議論していないので、私はそれを使用することをためらっていました。とにかく、私はコードを整理するつもりなら、それは最善の方法です。 残りのジレンマの場合、キャリー値に影響するために 'SHR MM、1'を使用し、キャリーが存在し、 'JNC iftrue'がある場合は' JC ifwrong'を使用できますか? 「MOV MM、CX」の代わりに「JPE ifwrong」と「JPO iftrue」を使用する方法がありましたか? 私たちはコードを実行するためにアセンブラを使用していないので、紙とペンだけでこれを確認することはできません。 – Axel1212

+2

'SHR MM、1'はそれを行う一つの方法ですが、CXをシフトさせたくないので一時的に余分なレジスタ(DXなど)が必要になります。その価値を破壊する。 Aki Suihkonenによって提案された「TEST CX、1」命令は、何も変更せずにビット0をテストするので、より良い選択です。 'MOV MM、CX'は動作しません。MOV命令はフラグレジスタを変更しないので、パリティフラグはセットされません。 –

+0

しかし、あなたはそれを掛けている、おめでとう! C - := –

2

test cx,1は、CXの最後のビットに基づいてゼロフラグを設定します。この場合、EqualまたはJZはcx%2 == 0に対応します。x-1によるマスキングはモジュラスをとる特殊なケースであり、xが2の累乗である場合にのみ適用されます。

関連する問題