2017-01-04 6 views
-3

私はアセンブラが言う私のプログラムを実行すると:それはRETに達したときにプログラムは、アセンブリ内のオペレーティング・システムに制御を返した8086

プログラムは、オペレーティング・システム

に制御を返しましたが、命令。コードは次のようになります。

twoMash PROC 
    push bp 
    mov bp, sp 
    sub sp, 2 

    NOT ax 
    ADD ax,1 

    mov sp,bp 
    ret 
twoMash ENDP 

mainがこのように定義されています

main: 
    mov ax,100b 
    push ax 
    call twoMash 
+0

あなたはどのアセンブラを使用していますか?また、質問は意味をなさない。あなたが*プログラムを実行するとき、*アセンブラ*は何かをしますか?問題を実行しているときにアセンブラは実行されません。コードをアセンブルしようとしているとき、またはバイナリを実行しようとしているときにこのメッセージが表示されますか?これは実際にはエラーであると確信していますか? –

+1

あなたの質問は何ですか? – fuz

+0

**「call twoMash」の後に**のコードは何ですか?あなたはそれを投稿していませんが、おそらくプログラムを終了させるでしょう( 'mov ax、4c00h'、' int 21h'のように)。 –

答えて

2

最初の命令はpush bpので、スタックの一番上の値は、今bpからの値です。

は、その後、あなたはsp(スタックの最上位へのポインタ)の操作を含め、いくつかのより多くのことを行うが、ちょうどret前に、それは古いbp値に戻って指します。

retはスタックから値をポップし、その値にip(命令ポインタ)を設定します。通常の状況下では、実行する次の命令のアドレスをスタックの先頭に置くことが期待されます(通常はcall命令を実行します)。retのカウンタアクションを実行し、callの次の命令のアドレスをスタックにプッシュしてからip引数の値はcall命令から)。

ipは値が古いbpに設定されています。この値はスタックメモリ(または「悪い」)のどこかを指している可能性が高いので、次にCPUがデータバイトをコードとして実行しようとします。 (OSへの復帰は実際には素晴らしい結果に終わりますが、そのような間違いは通常アプリケーションのクラッシュやデータの消失で終わります)。

修正するには、pop bpretの前に追加してください(の値をmov sp,bpに戻した後)。あなたはcall/retにより、スタック、明示的push/popまたはadd/sub sp、または暗黙的で操作するたび

、あなたはさらに、スタックを使用する前に、すべてのコードパスで正しいsp値で終わることを確認してください。つまり通常はpushにはpopのペアが必要で、すべてのcallretで復帰する必要があります。ただし、そのようなルールを破るのに十分な経験がなければ、別の方法で正しい状態にスタックを調整する必要があります。


ところで、それは実際にがあなたのエントリポイントでのスタックでリターンアドレスがあり(これを-ingいくつかの他のコードcallを持っている場合、それは、あなたの質問から明らかではない、またはそれがあるかどうか、疑問ですあなたのプログラムのエントリーポイント)。

これはDOS実行可能ファイルのようなもので、エントリポイントだった場合は、int 21h, 4Ch OSサービスコールでプログラムを終了する必要があります。

関連する問題