4

x86アセンブリでクイックソートに取り組んでおり、配列A[pivot]とA[j]の2つの要素を交換する必要がありますが、要素を交換するどころか、配列インデックスに値を割り当てることもできません。

配列は次のように割り当てられます。

A:      .long   2,1,8,6,12

私の元のスワッピングのスキームはまったく機能しなかったので、問題がどこにあるかを理解するためにこれに減らしました。正しい結果を得るためにさまざまな方法を試しましたが、すべて間違った値またはセグメンテーションエラーが発生します

    movl    A(,%ebx,4), %eax            #eax = A[pivot]
    movl    A(,%edi,4), %edx            #edx = A[j]


                                        #ebx = pivot = 0
                                        #edi = j = 1

    pushl   %eax
    pushl   $test7                      #"A[pivot] = %d"
    call    printf
    addl    $8, %esp                    # A[0] = 2 

    pushl   %edx
    pushl   $test8                      #"A[j] = %d"
    call    printf
    addl    $8, %esp                   #A[1] = 1

このスニペットは以下を返します:

A[pivot]         = 2 
A[j]             = -143535296 

A [pivot] = A [0] = 2なので、これは正しいですが、A [j] = A [1] = 1

これは、%ebxと%ediがその内容を表示したり値を変更したりするための2つの配列インデックスである場合に、配列要素を参照する正しい方法ですか。

私が間違っていることを理解することはできません、どんな助けもいただければ幸いです。

編集:また、printf引数としてA(、[index]、4)を使用すると、正しい値が表示されます。

edit1:printfステートメントが正しくない理由を理解し、コードを変更すると、正しいメモリアドレスと思われるものが返されました。addr [A]=134513652およびaddr[A+ 1] =134513656。配列の値を変更するという私の元の問題はまだ存在しますが、これを実行するとセグメンテーション違反が発生し続けます。

    leal    A(,%ebx,4), %ecx        # ecx = addr[A[0]]          
    movl    A(,%edi,4), %edx        # edx = A[1]
    movl    %edx, (%ecx)            # (ecx) = edx
4

1 に答える 1

1

特に呼び出し規約について読む必要があります。呼び出し先と呼び出し元の保存レジスタ。多くの ia32 呼び出し規則では、EAX、ECX、および EDX が呼び出し元保存レジスタです。つまり、呼び出し - あなたの場合は最初の printf 呼び出し - が値を変更する可能性があります。これは、呼び出し元として、プッシュ/ポップ命令などで値を保存する責任があるため、呼び出し元の保存と呼ばれます。あなたの例は、呼び出し先の保存されたレジスタの 1 つを使用して修正することもできます。

于 2013-03-18T17:24:23.187 に答える