2

負の数で算術演算を実行する電卓を作成しようとしています。このコードは、入力された数値を ASCII 値に変換するために使用されます。このプログラムを変更して、入力が負の場合に 2 の補数変換を実行し、目的の出力が得られるようにしたいと考えています。

現在、これは私の電卓の流れです:

-1+2=66675 (1 のはずです)

-1-1=656745 (-2 のはずです)

-1*-1=66757 (1 のはずです)

誰かが、コードのこの部分を変更して、必要なことを実行する必要があるとアドバイスしてくれました。私は最善を尽くしましたが、うまくいきません。これで私を助けることができますか?ところで、私は組み立てに本当に慣れていません..

CONVERT_ASSCII PROC NEAR

    MOV AH , BYTE PTR RESULT        ;MOVE FIRST TWO BYTE OF RESULT TO AX
    MOV AL , BYTE PTR RESULT + 1

    ;AT FIRST CHECK IF AX IS POSITIVE OR NEGETIVE
    TEST EAX , 8000H                    ;CHECK THE LAST BIT . IF THATS 1 THEN AX IS NEG , OTHERWISE THATS POSITIVE
    MOV EDI , 0                     ;AT FIRST SET OUR FLAG TO ZERO
    JZ EAX_POSITIVE                 ;AX IS POSITIVE
    NEG EAX                         ;CALCULATE NEGETIVE OF AX 
    MOV EDI , 1                     ;DI INDICATES THAT AX IS NEG

EAX_POSITIVE :
    MOV ECX , 10
    LEA ESI , ASSCII_NUM
    ADD ESI , 29                        ;MOVE TO THE LAST SPACE

    MOV EBP , 0                     ;THIS IS THE COUNTER OF CHARS

    ASSCII_LOOP : MOV EDX , 0
                  DIV ECX 
                  OR DL , 30H       ;MAKE REMINDER ASSCII
                  MOV [ESI] , DL        ;PUT ASSCII IN ASSCII_NUM
                  DEC ESI
                  INC EBP           ;ADD ONE TO THE CHAR'S COUNTER
                  CMP EAX , 0       ;IF AX > 0 GOTO 
                  JA ASSCII_LOOP    ;ASSCII_LOOP

    CMP EDI , 0                     ;CHECK IF THAT WAS A NEGETIVE NUMBER
    JZ REST                         ;IF THATS NOT NEGETIVE GOTO REST
    MOV DL , '-'
    MOV [ESI] , DL                  ;ADD A MINES SIGN TO THE STRING
    DEC ESI
    INC EBP

REST :
    LEA EDI , ASSCII_NUM

    ;MOVE THE ASSCII CODE TO IT'S RIGHT PLCAE IN ASSCII_NUM
    ORDER_ASSCII : INC ESI
                   MOV AL , BYTE PTR [ESI] 
                   MOV BYTE PTR [EDI] , AL
                   INC EDI
                   DEC EBP
                   CMP EBP , 0
                   JA ORDER_ASSCII

    MOV CL , '$'           
    MOV BYTE PTR [EDI] , CL         ;AT LAST PUT A DOLLOR SIGN AT THE END OF ASSCII_NUM

    RET
CONVERT_ASSCII ENDP
4

1 に答える 1

1

問題を理解してから、言語を適用します。最初にCで記述し、次にアセンブリで記述します。

あなたはASCIIについて言及していますが、私はあなたのasciiからの変換を見ていません。

たとえば、「-1 + 2」と言った場合、入力はそれらのアイテムのASCII文字であることを意味します。

0x2D,0x31,0x2B,0x32

これを解析できる1つの方法は次のとおりです。

マイナス記号として認識する必要のある0x2Dは、演算を実行します。次に、ASCIIで0x31である数値1をヒットします。これらが10進数であると仮定して、0x30を取り除き、たとえば0xFを使用します。次の文字は+、0x2Bの演算子です。これで、戻って完全な数値1を取得し、その前に演算子を適用できます。しかし、レジスタサイズが必要です。これらの8ビット値または16ビットまたは32ビットまたは64ビットですか?0xFF、0xFFFF、0xFFFFFFFFなどを取得することを否定すると、8ビット1は0x01、16は0x0001などになります。したがって、現在の演算子は+、0x2B、次の文字は0x32、数値2、抽出する0xFです。 2.次の文字は文字列の終わりなので、8ビットの場合は-1、0xFF、8ビットの場合は2、0x02、0xFF + 0x02 = 0x101、8ビットにクリップした場合は0x01、結果-1+ 2 = 1の場合、それをASCIIに戻す必要があります。

"-1*-1" is 0x2D,0x30,0x2A,0x2B,0x30

問題は、2つの演算子が0x2A、次に0x2Bの行にある場合に発生します。この場合、人間としては、どちらの場合もマイナス記号が後続の数値を否定することを意味していることがわかります。その後、乗算を実行します。

それらをサポートする場合は、より大きな数も処理する必要があります。

"12+34" 0x31,0x32,0x2B,0x33,0x34

0x31は0x1からの数値ストリップですが、0x32も数値なので、0x1に10を掛けてから、0x32からストリップした2を加算して、その数値を累積しているもの(10進数の12)に0xCを与え、次にプラス記号0x2B、次に他の数値も同じように処理され、0x33から3を削除して10を掛け、0x34から削除した4を加算して10進数の34(0x22)を求め、次にこれら2つの数値0x0C + 0x22 = 0x2E(10進数の46)を加算します。その場合、目的の結果は「46」のASCII文字列である0x34,0x46であると想定します。0x2eは10より大きいので10で割る必要がありますが、最初の桁を4にするには、余り(10を法とする)は6であり、10以下なので、変換は6になります。 0x36。

ターゲットにNEGがある場合は、AND、OR、ADD、NOT、および場合によってはNEG操作を使用します(それ以外の場合は、notを使用して1を追加します)。直接NOT命令がない場合は、すべてのものを使用したxoringはNOT操作であることに注意してください。(基本的に、ターゲットとする命令セットで使用可能な基本的な操作)非常に快適なプログラミング言語、またはこれらの種類の操作とバイト処理をサポートする少なくとも1つの言語でアルゴリズムを実装およびテストし、アルゴリズムを機能させて完了します。高水準言語の各操作とadd、not、subなどの操作をアセンブリに変換するだけです。アセンブリに簡単に変換できるフォームに似る前に、高級言語でソリューションを何度も繰り返す必要がある場合があります。今すぐ組み立てが苦手な場合は、このタスクを完了するのにかかる複雑さと時間を倍増させます。アルゴリズムの作成とデバッグ、およびアセンブリの学習をすべて同時に行うことは、2倍の作業ではなく、4倍以上の作業になります。分割統治。制御された環境でアルゴリズムを開発し、それをターゲット言語で実装します。

-1 + 2 = 66675(1である必要があります)0xFFFF ... FFFF + 0x000 ... 00002 = 0x1000000 ... 000001、0x0000 ... 00001にクリップ(任意のレジスタサイズを使用しています)66675=0x10473。どうやってそのような数に到達したのかよくわかりません。

-1-1 = 656745(-2である必要があります)0xFFFFF .... FFFFF + 0xFFFFFF ... FFFFF = 0xFFFFFFF...FFFFFFE。656745 = 0xA0569

-1 * -1 = 66757(1である必要があります)

これらの結果がどうなるか知りたいです

-1+1
-1+3
-2+1
-2+2
-1*-2
-1*-3
-2*-1
-2*-2

電卓を使用しています。そうすると、結果にパターンが表示されるようになる場合があります。

問題を半分に分割します。数学演算の正しい結果を計算していて、ASCIIの結果だけが壊れていると確信していますか?または、ASCIIが機能し、数学演算が壊れた結果ですか?16進数は簡単で、8進数は変換がさらに簡単で、簡単なチェックのために逆方向の処理を行う必要はありません。結果を確認した後、手動で逆方向に戻すことができます。

while(ax)
{
   dl = (ax&7)+0x30;
   string[ptr++]=dl;
   ax>>=3;
}
string[ptr]=0;

次に、文字列を表示します。手で文字列を反転し、電卓を使用して8進数から10進数に変換し、結果を確認します。マイナス2(-2)は0xFFFFF .... FFFFEになるため、8進数では、67777777777....7777777の逆の順序で表示されます。したがって、文字列を逆にすると、電卓は16進値0xFFFFF....FFFEに到達します。電卓を使えば、良い結果が見やすいはずです。

(はい、16ビットレジスタでx86を使用していることはよく知っています)

于 2013-02-12T05:51:41.123 に答える