0

私はasmをたくさん扱っているCの本を読んでいて、GDBでレジスターとメモリーを見ています。問題は、まったく同じソースをコンパイルして分解すると(実際には、本のCDに付属のソースファイルを使用して)、組み立て手順が本の内容とはかなり異なって見えることです。この本はIntelフレーバーのアセンブリを使用しており、gdbに「setdisassembly intel」を入れているので、そうではありません。手順が異なるだけで、いくつかはすべて一緒に異なり、他にもいくつかの癖があります。

たとえば、この本では、eipレジスタにmov命令があります。

(gdb) x/i $eip
mov DWORD PTR[ebp-4], 0x0

forループで変数iを0に初期化することに対応します(i = 0、i <10、i ++)

ただし、私のgdbコンソールでは、ブレークポイントが同じ場所にあります(set break main; run)。次のように表示されます。

(gdb) x/i $eip
mov DWORD PTR[esp+0x1c], 0x0

別のレジスタをすべて一緒に参照していることに注意してください。espの値を確認すると、ebpではなくespであり、それ自体が0x1cです。しかし、0x1cまたはesp + 0x1cにあるものを調べてみると、それらのアドレスを見ることができないことがわかります。

それで、本が進むにつれて、それはebp、ebp-4などにあるものの軌跡をたどり始めるので、私はまったく従うことができません、そして私のasmでは何も起こっていないようですebpレジスタ

この本は2008年に書かれたので、gccまたはgdbのバージョン変更がその重要な変更を導入するほど古くなっているとは想像できません(またはそれを行いましたか?)...コンパイラの最適化がある可能性はありますかまたは、デフォルトでオンになっているもので、そのような異なる結果が生成されていますか?

前もって感謝します

編集:奇妙な。私はそれぞれの提案を試しましたが、何も機能しませんでした。次に、rm a.outを実行し、新しく再コンパイルしました。これで正常に動作します(手順は本とは異なりますが、本のアドレスに対応するアドレスを調べることができます。対応するパターンに従うことができれば、すべて問題ありません。まったく同じasmである必要はありません、それはそれを簡単にしすぎるでしょう!)すべてのあなたの助けと提案にもう一度感謝します。

4

3 に答える 3

1

これを引き起こす可能性のあるものは何百万もあります。別のアーキテクチャでコードをコンパイルした場合、これを期待します(いいえ、必ずしも32ビットと64ビットを意味するわけではありません。文字通り、異なるCPUアーキテクチャでも、後で説明するように実行順序を変更できます)。 。最適化を使用してプログラムをコンパイルすると、CPUのパイプラインを最大限に活用するために、実行の順序が変更されます。これは、いくつかのNOOP命令を追加すること、またはそれらを完全に並べ替えることを意味する場合があります(もちろん、理由の範囲内で)。さらに、一部のCPUには複数の方法があり、通常は一方が他方よりも高速です(Intel LOOP命令が思い浮かびます。最近のコンパイラは、この命令がひどいため、ペストのように避けています)。あるレジスタが別のレジスタよりも効率的である場合、それを使用します。

物語の教訓:学習目的のために、著者と読者の両方がすべての最適化を無効にする必要があります。追加のボーナスポイントについても、同じバージョンのgccと同じプラットフォームを使用してください。

于 2012-02-09T04:50:09.830 に答える
1

-fomit-frame-pointersコンパイルしたコードは、GCC-4.6でデフォルトになったでコンパイルされたようです。

明示的にビルドしてみてください-fno-omit-frame-pointer。結果は本にもっと近くなると思います。

于 2012-02-09T05:42:54.730 に答える
0

これはすべて、プラットフォームとコンパイラに固有のものになります。恐れ入りますが、できることはあまりありません。

于 2012-02-09T04:48:51.127 に答える