3

学生が組み合わせの計算を練習できるように、アセンブリ言語(MASM)でプログラムを作成しました。プログラムはランダムにnとrを割り当て、組み合わせを計算してから、生徒に答えを提供するように促します。問題は解決しました*ほとんどの場合、プログラムは正常に機能していますが、学生から提供された整数文字列をプログラムで計算された結果と比較できる整数に変換する際に、いくつかの課題に直面しています。以前は問題なくesiを使用していましたが、何らかの理由で、プログラムがesi(または文字列のアドレス)の内容を評価して整数に変換するポイントに到達すると、デバッガーはその内容を表示しますesiのは文字列の最初の文字ではありません。* 明確にするために、私はReadIntに精通していますが、ReadIntを使用せずに整数を解析する方法を理解しようとしています。

アップデート: ユーザーが有効な数値を入力する限り、プログラムは正常に機能するようになりました。esiが適切な場所を指していないという問題を解決しました。また、入力された値が実際に数値であることを確認するために、いくつかのエラーチェックを行いました。ただし、最初はエラーチェックにより、次の反復で有効な数値が入力されたときに無効な入力が行われた後、プログラムは「無効な入力」というメッセージを返し続けました。コードの最初の行にtryAgainタグを配置すると、有効な入力が無効な入力の後に続く場合でも、プログラムは無効な入力メッセージを返し続けます。最初に、tryAgainタグを現在の位置に配置しようとしましたが、無限ループで実行されていると思います。次に、プログラムがinvalidInputにジャンプした場合に変数をリセットしようとしましたが、それはできませんでした。

編集:明確にするために、これはx86プロセッサ用です。

コードは次のとおりです。

.data
result  DWORD   ?
temp        BYTE        21 DUP(0)
answer  DWORD   ?

.code
main    PROC

(いくつかの予備手順の呼び出し)

push OFFSET temp        ;ebp+16
push OFFSET answer      ;ebp+12
push answerSize     ;ebp+8
call    getData

(より多くのプロシージャ呼び出し)

exit        ; exit to operating system
main ENDP

編集されたコード:

;*************************************************
; prompts / gets the user’s answer.
; receives: the OFFSET of answer and temp and value of answerSize
; returns: none
; preconditions: none
; registers changed:  eax, ebx, ecx, edx, ebp, esi, esp
;*************************************************
getData PROC
push        ebp
mov     ebp,esp

tryAgain:
mWriteStr   prompt_1
mov     edx, [ebp+16]       ;move OFFSET of temp to receive string of integers
mov     ecx, 12
call        ReadString
cmp     eax, 10
jg      invalidInput

mov     ecx, eax        ;loop for each char in string
mov     esi,[ebp+16]    ;point at char in string

pushad
loopString:             ;loop looks at each char in string
    mov     ebx,[ebp+12]
    mov     eax,[ebx]   ;move address of answer into eax
    mov     ebx,10d     
    mul     ebx         ;multiply answer by 10
    mov     ebx,[ebp+12]    ;move address of answer into ebx
    mov     [ebx],eax       ;add product to answer
    mov     al,[esi]        ;move value of char into al register
    inc     esi         ;point to next char
    sub     al,48d      ;subtract 48 from ASCII value of char to get integer  

    cmp     al,0            ;error checking to ensure values are digits 0-9
    jl      invalidInput
    cmp     al,9
    jg      invalidInput

    mov     ebx,[ebp+12]    ;move address of answer into ebx
    add     [ebx],al        ;add int to value in answer

    loop        loopString  
popad
jmp     moveOn
invalidInput:               ;reset registers and variables to 0
    mov     al,0
    mov     eax,0
    mov     ebx,[ebp+12]
    mov     [ebx],eax
    mov     ebx,[ebp+16]
    mov     [ebx],eax       
    mWriteStr   error
    jmp     tryAgain
moveOn:
    pop     ebp
    ret     12
getData ENDP

これで私がどこに向かっているのかがわかるように、これが私の擬似コードです。

擬似コードが更新されました

  1. 文字列の先頭から開始

  2. 回答の値に10を掛けます。

  3. 文字列から各文字を分割し、48dを引いて整数を取得します。元。学生は156を入力します。49は変数tempの最初の文字として格納されます。49から48を引きます。整数は1です。

  4. 回答の値に整数を追加します。

  5. Inc esi(1文字右に移動)。

  6. ループ。

4

2 に答える 2

1

文字列から各文字を分割し、48dで除算します。

除算ではなく、減算したい。

問題についてはesi、この関数がどのように呼び出されるかを示してください。バッファ[ebp+16]のオフセットではないか、バッファオーバーフローが発生している可能性があります。デバッガーを使用して、そのアドレスにメモリ書き込みウォッチを設定し、誰がそれを変更したかを確認することもできます。

また、あなたのラベルはコードに含まれていませんが、ラベルが間違った場所にあるinvalidInputと思われます。tryAgainあなたはおそらくプロローグの後にそれが欲しいでしょう。

ちなみに、この変換を行う一般的な方法は、文字列の先頭から先に進み、各ステップで部分的な結果に10を掛け続けることです。そうすれば、関数は必要ありませんPowerTen

更新:4バイトをロードしているため、文字列から一度に4文字をロードしているため、予期しない値が表示されます。mov eax,[esi]する代わりmovzx eax, [esi]mov al, [esi]

于 2012-12-01T23:30:00.523 に答える
0

で現在の文字列インデックスポインタからバイトを移動する[esi] には次のいずれかを使用する必要があります。

movzx   eax, byte ptr[esi]
; or
mov     al, byte ptr[esi]

BYTE PTResiのアドレスで1バイトを処理することをMASMに通知します。

私はあなたがこれを望んでいるかどうかわかりません:

tryAgain:
    push    ebp
    mov     ebp, esp
    mWriteStr   prompt_1 

ユーザーが悪いプロンプトを入力し、にジャンプするたびにtryAgain、「スタックのセットアップ」を続けます。多分これ:

    push    ebp
    mov     ebp, esp

tryAgain:
    mWriteStr   prompt_1 
于 2012-12-02T01:02:21.283 に答える