1

MASM615 で与えられた手順を書き直したい。私は単に「USES」ディレクティブを使用するつもりなので、スタックとの間ですべてのプッシュとポップを行う必要はありません。これにより、手順で参照されるアドレスの一部がスタック ポインター (esp) を参照するため、明らかに変更されます。私はそれを適切に実装したと思っていましたが、プログラムは私にかかっています。この手順は、コード ストリームに直接書き込まれた文字列を出力し、文字列をコードとして実行しようとして CPU がエラーを出さないように、文字列をスキップすることになっています。以下は私が与えられた手順です:

WritePrompt PROC
push ebp
mov ebp, esp           ; set up the ebp pointer
push esi               ; save used reg
push eax               ; save used reg
mov esi, [ebp+4]       ; use ret.addr. as string pointer 

L1:  cmp BYTE PTR [esi], 0  ; check for the end of string
jz L2                  ; jump if the string is over

mov al, [esi]          ; get the next string character
call WriteChar         ; ... and output it
inc esi                ; increment the string pointer
jmp L1

L2:  inc esi                ; adjust the string pointer
mov [ebp+4], esi       ; modify the return address

pop eax                ; restore all used regs and exit
pop esi
pop ebp
ret
WritePrompt ENDP

それが私が与えられたものであり、以下はスタックのプッシュとポップをスキップするためにUSESディレクティブを使用して単純化された書き直しです:

outStr PROC USES eax ebp esi
mov ebp, esp
mov esi, [ebp]

L1:
cmp BYTE PTR [esi], 0
jz L2

mov al, [esi]
call WriteChar
inc esi
jmp L1

L2:
inc esi
mov [ebp], esi

ret
outStr ENDP

このプロシージャが呼び出されると、プログラムがハングします。なんで?どうしたの?プッシュとポッピングによる変更をすべて説明したような気がします。

編集:デバッグのために「call dumpregs」をいくつか追加した後、プログラムをクラッシュさせる行が「cmp BYTE PTR [esi]、0」であることがわかりました。これにより、スタックから文字列へのポインターを適切に取得していないと思います. 「mov esi, [ebp + 4]」を使用すると、少なくとも遠くまで行けるように見えますが、すぐに L2 にジャンプします。

編集2:

問題が見つかりました。私が使用しているドキュメントでは、USES ディレクティブの機能が非常に不明確です。すべての「使用済み」レジスタをスタックにプッシュし、その後、USES ディレクティブなしで行われるのと同じようにポップします。したがって、使用する必要のあるコマンドは次のとおりです。

mov ebp, esp
add ebp, 12
mov esi, [ebp]

私はまだ自分の質問に答えることができないので、ここに置く必要があると思います. この質問は終了しました。とにかくありがとう!

4

1 に答える 1