2012-03-11 9 views
0

私は次の例を示す本を読んでいます: 各メンバーは次のメンバーのアドレスを4番目の最初のバイトに持つリストがあります。最後のメンバーが、それは次の実装が間違っていると言うの0の値を持っており、私は理由を理解していない:アセンブリ - 間違ったフリーリストの実装

freeList 
    mov eax, [ebp+8] 
    cmp eax, 0 
    jne cont 
    ret 
cont: 
    mov ebx, [eax] 
    mov [ebp+8], ebx 
    push eax 
    call free 
    pop eax 
    call freeList 

を(私は、私は1つを持って、正しい実装を必要としない、私はちょうど必要とします。これと何が悪いか理解する)

ありがとう。

+0

最後の 'call freeList'は私には間違っています。私の最高の推測は' jmp freeList'と言うべきです。 – Neil

+0

@ Neeil:正解では、本当にjmpです。何が問題なの? –

答えて

2

不正な実装の最後の行はcall freeListです。しかし、(再帰的な)呼び出しが完了すると、その行の後に存在しないコードに戻ることを試みます。 ret命令を追加するとコードは機能しますが、通常はコードをデバッグするときを除いてすべての中間呼び出しを見ることができます。代わりにcall freeList; retを簡略化してjmp freeListにすることができます。高レベルのコードをデバッグするの

例:

function freeList(list) { 
    if (list) { 
     var next = list->next; 
     free(list); 
     freeList(next); 
    } 
} 

あなたが最適化してコンパイルすると、コンパイラはしかし、これは破壊するであろう、listnextコーピングとjmpを実行することにより、freeList(next)への再帰呼び出しを記述することもできますlistの値。つまり、関数をデバッグしようとすると、リストのどの要素がすでに解放されているかはわかりません。したがって、関数の問題をデバッグしようとしているときに、この最適化を無効にしたい場合があります。

+0

それでは、それぞれの 'call X 'の後にalwayを置いて、' ret'を書く必要がありますか? –

+0

何かを書く必要があります。なぜなら、コールは(中断または終了をコールしていないか、同様に致命的なものでなければ)、ある時点で次のステートメントに戻るからです。 – Neil

0

これが関数であると仮定すると、スタックフレームを呼び出す前にスタックフレームを設定してから呼び出した後にフレームを巻き戻す必要があるため、これを直接呼び出すことはできません。これはまた、ほとんどのシステムABI(EAX、ECX、EDXのみがスクラッチレジスタである)に反してEB​​Xを保存しない。

これはインラインコードであれば、現在のフレームを巻き戻す必要があるない)。

関連する問題