私は1982年にCP/M-80以降のDigitalResearchOSでのPL/Mプログラムのアセンブリデバッグから始めました。これは、Microsoftがソースとアセンブリを同時に表示するコマンドラインデバッガであるsymdebを導入するまで、MS-DOSの初期の頃と同じでした。Symdebは飛躍的な進歩でしたが、以前のデバッガーでは、どのアセンブリコードがどのソースコード行に属しているかを認識することを強制されていたため、それほど大きくはありませんでした。CodeViewの前は、PhoenixTechnologiesのpfix86が最適なデバッガーでした。NuMegas SoftIceは、(純粋なハードウェアICEを除いて)これまでに出会った中で最高のデバッガーであり、アプリケーションをデバッグするだけでなく、Windowsの内部動作も簡単にガイドしてくれました。しかし、私は逸脱します。
1990年の終わりに、私が取り組んでいたプロジェクトのコンサルタントが私に近づき、彼が何日も取り組んできたこの(非常に初期の)C ++バグがあると言いましたが、問題が何であるか理解できませんでした。彼は私のために(ウィンドウ化された非グラフィックDOSデバッガーで)ソースコードをシングルステップで実行しましたが、私はすべて焦りました。最後に、私は彼に割り込んでデバッガオプションを調べ、レジスタとすべてを備えたソース/アセンブリの混合モードが十分にあることを確認しました。これにより、アプリケーションがNULLを含む内部ポインター(ローカル変数用)を解放しようとしていることが簡単にわかりました。この問題では、ソースコードモードはまったく役に立ちませんでした。今日のC++コンパイラには、おそらくこのようなバグは含まれていませんが、他のバグはあります。
アセンブリレベルのデバッグを知っていると、コンパイラが生成するコードを予測できる範囲で、ソース-コンパイラ-アセンブリの関係を理解できます。ここスタックオーバーフローの多くの人は「profile-profile-profile」と言いますが、これはさらに一歩進んで、どのソースコード構造(私はCで書いています)をいつ、どれを避けるべきかを学びます。これは、開発者が何も疑わずに大量のコードを生成できるC++ではさらに重要だと思います。たとえば、オブジェクトのリストを処理するための標準クラスがありますが、これには欠点がないように見えます。ほんの数行のコードとこの素晴らしい機能です。-それが生成する奇妙なプロシージャコールのスコアを見るまで。私はそれらを使うのが間違っていると言っているのではありません、私は」m開発者は、それらを使用することの長所と短所を認識している必要があると言っているだけです。演算子のオーバーロードは優れた機能かもしれませんが(私のようなWYSIWYGプログラマーにとっては少し奇妙です)、実行速度の代償は何ですか?あなたが「何もない」と言うなら、私は「それを証明する」と言います。
デバッグ時に混合または純粋なアセンブリモードを使用することは決して間違いではありません。難しいバグは通常見つけやすく、開発者はより効率的なコードを書くことを学びます。インタプリタキャンプ(C#およびJava)の開発者は、コードはコンパイルされた言語と同じくらい効率的であると言うでしょうが、アセンブリを知っていれば、なぜそれらが間違っているのか、なぜ完全に間違っているのかもわかります。あなたは微笑んで「ええ、それについて教えてください!」と考えることができます。
さまざまなコンパイラを使用した後、最も驚くべきコード生成機能を備えたコンパイラに出くわします。1つのPowerPCコンパイラーは、オプティマイザーの優れたコード解釈によって、3つのネストされたループを1つのループに凝縮しました。私は...まあ、別のリーグで言ってみようと書いた人の隣に。
約10年前まで、私はかなりの純粋なアセンブリを作成しましたが、多段パイプライン、複数の実行ユニット、そしてCコンパイラと競合する複数のコアを使用して私を打ち負かしました。一方、私はコンパイラーが何をうまく処理できるか、そして何を処理する必要がないかを知っています。GarbageInはGarbageOutと同じです。これは、アセンブリ出力を生成するすべてのコンパイラに当てはまります。