0

こんにちは、私はアセンブリ、技術的には HLA (High Level Assembly) の割り当てに取り組んでおり、助けが必要なバグです。課題は次のとおりです。
すべてのパラメーターが異なるかどうかを正しく識別し、この条件が満たされているかどうかに応じて EAX で 0 または 1 を返す関数を実装する HLA アセンブリ言語プログラムを作成します。この関数には、次の署名が必要です。

手続き allDifferent( x: int16; y : int16; z : int16 ); @nodisplay; @noframe;

以下に示すのは、サンプル プログラム ダイアログです。

Feed Me X: 205
Feed Me Y: 170
Feed Me Z: 91
allDifferent は true を返します。

Feed Me X: 0
Feed Me Y: 0
Feed Me Z: 0
allDifferent は false を返します。

Feed Me X: 121
Feed Me Y: 121
Feed Me Z: 121
allDifferent は false を返します。

これが私が持っているコードです。私の問題は、入力した数字に関係なく、常に「allDifferent returns false!」を返すことです。助けてくれてありがとう。

program allDifferent;
#include( "stdlib.hhf" );
static
iDataValue1 : int16 := 0;
iDataValue2 : int16 := 0;
iDataValue3 : int16 := 0;
iDataValue4 : int16 := 0;


procedure allDiff( x: int16; y : int16; z : int16 ); @nodisplay; @noframe;
static
returnAddress : dword;
temp : int16;

begin allDiff;
pop(returnAddress);
pop(z);
pop(y);
pop(x);
pop(temp);

push(returnAddress);
push(AX);
push(BX);

mov(x, AX);
cmp(y, AX);
je xyequal;
jmp notequal;

xyequal:
mov(y, BX);
cmp(z, BX);
je equal;
jmp notequal;

equal:
mov(0, EAX);
jmp ExitSequence;

notequal:
mov(1, EAX);
jmp ExitSequence;


ExitSequence:
pop(BX);
pop(AX);
ret();
end allDiff;

begin allDifferent;
stdout.put( "Gimme a X:" );
stdin.get( iDataValue1 );
stdout.put("Gimme a Y:");
stdin.get(iDataValue2);
stdout.put("Gimme a Z:");
stdin.get(iDataValue3);

push( iDataValue1 );
push( iDataValue2 );
push( iDataValue3 );
push( iDataValue4 );
call allDiff;

cmp(EAX, 1);
je ISDIFFERENT;
jmp NOTDIFFERENT;


ISDIFFERENT:
    stdout.put("allDifferent retursn true",nl);
    jmp EndProgram;

NOTDIFFERENT:
    stdout.put("allDifferent retursn false",nl);
    jmp EndProgram;

stdout.newln();

EndProgram:


end allDifferent;
4

1 に答える 1

1
notequal:
mov(1, EAX);         <<- good.
jmp ExitSequence;
:
ExitSequence:
pop(BX);
pop(AX);             <<- not so good.
ret();

AX上記のシーケンスで何が起こっているかをよく見てください。コード内の何かに設定しても、その値を命令で上書きし、関数に入ったときの状態にpop戻します。AX

一般に、アセンブラー関数は、呼び出し元が使用している可能性があるレジスターを保存および復元する必要がありますが、そのレジスターを使用して有用な情報を返す場合はそうではありません。


さらに、パラメータが正しく処理されていません。それらを順番にプッシュします{p1, p2, p3, junk}(何にも使用しないため、4番目のパラメーターがある理由はわかりません)。

ただし、関数内では、 order でポップします{x, y, z, temp}。ここで、スタックは LIFO (後入れ先出し) 構造であるため、マッピングは次のようになります。

junk -> x
p3   -> y
p2   -> z
p1   -> temp

つまり、x変数は、渡した「実際の」パラメーターの 1 つではなく、任意の値に設定されます。

その 4 番目のパラメーターを使用しない場合は、削除することをお勧めします。ある時点でそれを使用したい場合は、プッシュ操作とポップ操作を関連付けて、正しい値を取得する必要があります。


余談ですが、いくつかの方法でコードをよりきれいにすることもできます。

まず、ローカルで (小さなブロックで)使用されるBXため、実際に使用 (または保存/復元) する必要はありません。チェックとチェックの両方に使用できます。AXmov/cmpAXxyyz

第二に、実際には必要のないかなりの数のジャンプを取り除くことができます。アルゴリズムの疑似コードは、非常に単純なものに要約できます。

    if x and y are same, go to NOTDIFF.
    if y and z are same, go to NOTDIFF.
DIFF:
    set AX to 1
    go to END
NOTDIFF:
    set AX to 0
END:
    return
于 2015-11-13T02:30:09.947 に答える