[解決済み] アセンブリでの再帰的フィボナッチ
質問
アセンブリで再帰的なフィボナッチ・プログラムを実装しようとしています。しかし、プログラムが処理されない例外でクラッシュしてしまい、問題を特定することができないようです。スタックの不適切な使用が原因であることは間違いないのですが、どこが原因なのかがわかりません。
.386
.model Flat
public Fibonacci
include iosmacros.inc ;includes macros for outputting to the screen
.code
Fibonacci proc
MOV EAX, [EBP+8]
CMP EAX, 1
JA Recurse
MOV ECX, 1
JMP exit
Recurse:
DEC EAX
MOV EDX, EAX
PUSH EAX
CALL Fibonacci
ADD ESP, 4
MOV EBX, ECX
DEC EDX
PUSH EDX
CALL Fibonacci
ADD ECX, EBX
exit:
ret
Fibonacci endp
.data
end
また、フィボナッチ値を取得するために使用している数値を外部プロシージャでスタックにプッシュしています。どこに問題があるのか、何か思い当たることはありませんか?
解決方法は?
を実行すると
call
の場合、次の操作のアドレスが戻り値としてスタックにプッシュされます。関数を作成する際には、スタックフレームを作成することが一般的です。このフレームは、ローカル変数や引数のオフセットだけでなく、コールスタックを表示するために使用することができます。このフレームは、関数の最初にある2つの操作によって作成されます。
push ebp
mov ebp, esp
関数の終了時に、コールスタックを削除するには
leave
という2つの操作の逆を行うことに相当します。スタックフレームを使用する場合
esp
に格納されます。
ebp
フレームベースと呼ばれるスタック上の位置を指すようにします。このアドレスの上には、古い値である
ebp
とリターン・アドレスを指定すると、通常、最初の引数を取得するために
[ebp+8]
. しかし、スタックフレームを設定しませんでした。つまり、古い値である
ebp
はスタックにプッシュされず、現在の値である
ebp
がどこにあるか分からないので、引数の取得に使用することはできません。したがって、引数を取得するには
[esp+4]
.
また、返り値は慣習的に
eax
と
ebx
は呼び出し側で保存されます。あなたのコードは、このどちらの規則にも従っていません。また、技術的には、関数は必ずしも
ecx
または
edx
そのため、通常、それらを保存したい場合は、他の関数を呼び出す前にスタックにプッシュしておく必要があります。このコードでは
edx
と
ebx
は、2以上の値で呼び出されると上書きされ、不正な結果を引き起こします。
ここに、私が言及したすべての修正を含む完全なリストを示します。スタックフレームを作成する必要はなく、あなたのコードもそうなっていないためです。
.386
.model Flat
public Fibonacci
include iosmacros.inc ;includes macros for outputting to the screen
.code
Fibonacci proc
MOV EAX, [ESP+4]
CMP EAX, 1
JA Recurse
MOV EAX, 1 ; return value in eax
JMP exit
Recurse:
PUSH EBX ; preserve value of ebx
DEC EAX
PUSH EAX
CALL Fibonacci
MOV EBX, EAX ; ebx is preserved by callee, so it is safe to use
DEC [ESP] ; decrement the value already on the stack
CALL Fibonacci
ADD EAX, EBX ; return value in eax
ADD ESP, 4 ; remove value from stack
POP EBX ; restore old value of ebx
exit:
ret
Fibonacci endp
関連
-
[解決済み】テスト %eax %eax のポイント【重複あり
-
[解決済み] MIPS srlを変数で指定
-
[解決済み] アセンブリで数字をASCIIに変換する
-
[解決済み] MIPSのコードのこの部分で、oriはどのように使われているのですか?
-
[解決済み] BL命令ARM - その仕組み
-
[解決済み] x86アセンブリで160x100モードを実現する
-
[解決済み] SRLとSRAの違いは何ですか?[重複しています]。
-
[解決済み] アセンブリ言語 jeジャンプ機能
-
[解決済み] インテルアセンブリの%ripレジスタを理解する
-
[解決済み] MIPSのオペコードにおけるlaとliの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】単純なforループのためのMIPSアセンブリ
-
[解決済み】アセンブリJLEのjmp命令例
-
[解決済み] Lc3分割のしくみ
-
[解決済み] MIPSの左シフト
-
[解決済み] MIPSのコードのこの部分で、oriはどのように使われているのですか?
-
[解決済み] オブジェクトファイルのシンボルテーブルとリロケーションテーブル
-
[解決済み] アセンブリMIPS。配列の初期化および合計
-
ファイルまたはアセンブリを読み込めませんでした ... 不正なフォーマットでプログラムをロードしようとしました。
-
[解決済み] ARMv8でリテラル0ではなく、xzrレジスタを使用するのはなぜですか?
-
[解決済み] MIPSプログラムにおける`lw`と`sw`の実際の働きを理解する。