1

以下は、アセンブリ言語クラスの宿題の問題です。gdbのCから生成されたX86コードを読み取ってY86コードを作成します。この関数の目的は、リンクリストの要素を合計することです。

関数は現在立っているので、動作します!プログラムの終了時に、正しい値が%eaxレジスタに含まれています。残念ながら、それはハックのためにのみ正しいです。halt関数の最後、命令の直前に命令を追加しましたret。コメントを外すと、ret命令を実行するとPCが0x0に設定されているように見えます。言い換えれば、それは最初からやり直しのように見えます。それがすべきことは、それが呼び出されたポイントに戻ることです。無限ループに入ります。

コードは次のとおりです。Y86シミュレーターがインストールされている場合は、スタンドアロンです。

.pos    0
init:    irmovl Stack, %esp  
irmovl    Stack, %ebp  
jmp     Main  

Main:  
    irmovl  ele1, %eax  
    pushl   %eax  
    call    sum_list  
    halt  

sum_list:  
    pushl   %ebp  
    rrmovl  %esp, %ebp  
    irmovl  $16, %edx  
    subl    %edx, %esp  
    irmovl  $0, %edx  
    rmmovl  %edx, -4(%ebp)  
    jmp     L2  

L3:
    mrmovl  8(%ebp), %eax
    mrmovl  (%eax), %eax
    mrmovl  -4(%ebp), %edx
    addl    %eax, %edx
    rmmovl  %edx, -4(%ebp)
    mrmovl  8(%ebp), %eax
    mrmovl  4(%eax), %eax
    rmmovl  %eax, 8(%ebp)

L2:
    irmovl  $0, %ecx
    mrmovl  8(%ebp), %edx
    subl    %ecx, %edx
    jne     L3
    mrmovl  -4(%ebp), %eax
    rrmovl  %esp, %ebp
    popl    %ebp
    halt #THIS DOESN'T BELONG. COMMENT OUT TO SEE BAD BEHAVIOR.
    ret

#linked list
.align  4
    ele1:
            .long   0x00a
            .long   ele2
    ele2:
            .long   0x0b0
            .long   ele3
    ele3:
            .long   0xc00
            .long   0


    .pos    0x300
    Stack:

ご協力いただきありがとうございます!

4

3 に答える 3

4

sum_listこれがエラーの原因である場合とそうでない場合がありますが、スタックフレームを誤って破棄していると思います。次のように設定します。

pushl   %ebp  
rrmovl  %esp, %ebp

しかし、あなたはそれを次のように分解します:

rrmovl  %esp, %ebp
popl    %ebp

%espどちらの場合もからにコピーすることに注意してください%ebp。これは、分解によってセットアップの機能が元に戻されるため、正しくありません。代わりに、

rrmovl  %ebp, %esp
popl    %ebp

または単に

leave

同じことをします。

于 2011-05-13T16:56:48.323 に答える
0
mrmovl  -4(%ebp), %edx

ここに問題があります。ebp-4には差出人住所があるので、それを上書きしています。別の場所を使用すると、すべてがうまくいきます:)

于 2011-05-13T16:49:28.037 に答える
-1

スタック操作に関連する2つ(および半分)の問題があります。

フレームは正しく設定されていますが、分解部分は失敗します(プログラムは、rrmovl%ebp、%espの代わりにrrmovl%esp、%ebpを実行します)

前のフレーム(つまり、呼び出し元のフレーム)に保存されているパラメーターにアクセスしようとして失敗します。スタックは上から下に実行され、スタックに格納される最後の要素はリターンアドレスと古いフレームポインタであるため、ebpレジスタが変更されると、呼び出し先は、で始まるプログレッシブオフセットを介して呼び出し元の関数の引数を直接参照できます。 8(%ebp)。

半分のエラーは、メイン関数が終了する前にスタックの保存されたパラメーターをポップしないことです。

発信者と着信者の規則については、Y86ブログ(http://y86tutoring.wordpress.com/2012/10/31/functioning-stacks/ )で説明されています。

于 2012-11-08T14:41:21.063 に答える