コード行はCPUによってどのように実行されますか?


11

私は、高級言語がマシンコードに正確に変換され、CPUによって実行される方法を正確に理解しようとしています。

コードがマシンコードにコンパイルされることを理解しています。これは、CPUが使用できる低レベルのコードです。割り当てステートメントがある場合:

x = x + 5;
y = x - 3;

CPUは一度に1行ずつ実行しますか?したがって、最初にx = x + 5を実行します。CPUが実行する次の命令はy = x-3です。私は本当に実行プロセスと、書いたコードがCPUによって実際に実行される方法を理解しようとしています。


オープンソースCPUの1つの設計を理解したいと思うかもしれません。excamera.com/ sphinx / fpga - j1.htmlのような本当にシンプルなスタックベースの実装があります -それらは3アドレスアーキテクチャよりもはるかに単純ですあなたの例のように。
SKロジック

3
私がこのビジネスに参入したとき、これはシンプルで明確な答えを持っているでしょう。現在、CPUは非常に複雑であり、あらゆる種類の処理を実行して処理能力を向上させています。
デビッドソーンリー

回答:


12

コードの行は、CPUがコードを実行する方法とは関係ありません。アセンブラーを読むことをお勧めします。これにより、ハードウェアが実際にどのように処理するかについて多くを学ぶことができます。また、多くのコンパイラからアセンブラ出力を取得できます。

そのコードは、次のようなものにコンパイルされます(組み立てられたアセンブリ言語で):

load R1, [x] ; meaning load the data stored at memory location x into register 1
add R1, 5
store [x], R1 ; store the modified value into the memory location x
sub R1, 3
store R1, [y]

ただし、変数が再び使用されないことがコンパイラーにわかっている場合、ストア操作は発行されない可能性があります。

デバッガーがプログラムソースの行に対応するマシンコードを知るために、コンパイラーによって注釈が追加され、マシンコードのどこに対応するのかを示します。


何故なの?3アドレスアーキテクチャにはADD Rx, Rx, $5andのような命令がありますSUB Ry, Rx, $3(xおよびy変数がレジスタにマッピングされていると仮定します)。ロード/ストアRISCアプローチについて説明しています。
SKロジック

1
@ SK-logic:データ型と操作を備えた非常に単純なプログラミング言語の非常に単純なコード行で発生する可能性がありますが、CPUはたまたま十分にサポートしますが、一般的なケースはありません。専門家にとっては便利ですが、最初に、機械語コード命令が一般的に高レベル言語のコード行にほとんど似ていないことを認識することが重要です。

@ SK-Logic:この特定の例でのみ機能します。ただし、一般的に、maxpolunは正しいです。高レベルの言語ステートメントは低レベルの言語に翻訳する必要があり、概念的に単純なことをするためにはより多くの「レッドテープ」が必要です。OPはこの変換の例を求めていたと思います。
アンドレスF.

1
SK-ロジック@:OPは「私は本当に正確にどのように理解しようとしていると彼の質問を始めた高レベルの [...]言語を」
アンドレスF.

1
@ SK-logicコンテキストは、「割り当てステートメントがある場合:[コードスニペット] CPUは各行を1行ずつ実行しますか?」です。-非アセンブラー言語のソースコードを意図しているように思えます。より一般的には、低レベルのマシンコードがどのように理解されているかを示す指標は見当たらず、いくつかのフレージング(線の話し方など)は誤解を示しています。それはあなたが暗示するほど不可能ではありません、誰もがいくつかの単純なマイクロコントローラー(私や他の人のように)に頭を投げられる喜びを持っているわけではありません。おそらくフランキーは明らかにすべきだろう。

2

場合によります。

非常に単純なマシンの初期の頃、はい、コードは一度に1行ずつ実行されていました。マシンが大型化、高速化、複雑化するにつれて、複数の命令を同時に実行する機能と、レジスタの操作よりもメモリの読み取りと書き込みの時間が長くなることがわかりました。

コンパイラーの最適化ではこれを考慮する必要があり、指定された行は「多かれ少なかれ」並列に実行でき、プロセッサーの一部はyの計算に取り組んでおり、別の部分は以前に計算された新しい値x(およびyの計算は、レジスタからの新しい値を使用していました)。

Control Data 6600は、この種のことを行った最初のマシンでした。整数の加算には300ナノ秒かかり、メモリ参照(読み取りまたは書き込み)には1000ナノ秒かかり、乗算および除算にはLOT時間がかかりました。必要な機能ユニットに応じて、最大で約10個の命令がすべて並行して実行できます。CDC 6600 FORTRANコンパイラーは、これらすべてのスケジューリングに非常に優れていました。


この場合、次の命令の入力は最初の命令の結果に依存するため、 順次実行する必要あります。
SKロジック

@ SK-logic:まったく違います。2行目の入力は、1行目の右側の結果に依存しますが、元のサンプルコードで見ることができるものだけに基づいて、結果のメモリへのストアに依存しない場合があります最初の行。xがvolatile(C / C ++)として宣言されていた場合、コンパイラは最初に結果を保存し、yの新しい値の計算を開始する前にメモリからITをリロードする必要があります。 (たとえば、割り込みハンドラー)が入り、2行の間にxを押します。
ジョンR.ストローム

私はxとyがレジスターであると仮定しました(そして、コードはCのようなものではなく3アドレスの疑似アセンブリー言語です)。この場合、両方の命令は不可避的に連続的です。それ以外の場合、OPはこの質問の代わりに2つ以上の異なる質問をする必要がありました。
SKロジック

プロセッサがその価値を「推測」しようとするのだろうxか?これにより、すでにコードが実行され、キャッシュに保存されます。
コロブキャニオン

マシンに依存しているレジスタであっても、命令が完全に連続して実行されると想定することはできません。6600には、プログラマーが自明なことをしたいという仮定に基づいて、順次のセマンティクスを強制するスケジューリングロジック(「スコアボード」)がありました。後のマシンはそのハードウェアを省略し、代わりにコンパイラーに依存して命令を注意深くスケジュールしました。それらの獣でアセンブリ言語プログラミングを行う人間のプログラマーは、彼ら自身のものでした。
ジョンR.ストローム

1

いいえ、高レベル言語と低レベル言語のコード行/命令間に1対1のマッピングはありません。実際、上記の両方の行は、次のような複数のマシンコード命令に変換されます。

  1. 特定のメモリアドレスからレジスタに値をロードする
  2. 値を変更する
  3. メモリに書き戻す

これらの指示の実際の詳細は、プラットフォームによって異なります。

これが物事の基本的な見方です。ただし、問題をさらに複雑にするために、最新のCPUは、特に実行パイプラインアウトオブオーダー実行マルチコアなどの技術を適用しています。これらの結果、CPUは複数のことを一度に実行します。たとえば、パイプラインは同じ処理ユニット内で後続の命令の異なるフェーズを並行して処理しますが、複数のコアは独立した命令を並行して処理します。


0

本の詳細を調べて、動作の詳細を確認する必要があります。おそらくコンパイラクラスも同様です。

基本的に、あなたの質問は2つの異なる側面に焦点を合わせています。

1)コードはどのようにマシンコードに変換されますか?

2)コードはいつ/どのように並列化を使用して計算されますか?

1)に対する答えは、使用する言語によって異なります(ただし、例では簡単なので、出力は同じになります)。コンパイラがマシンコードへの変換を行う方法は、言語の力の1つです。さらに、この例では考慮に入れる必要のあるいくつかの懸念があります。コードはデータをメモリにロードしたり、保存したりする必要があります。

最後に、並列化はプログラミングの観点から強制できる機能ですが、一言で言えば、一部のプロセッサは独立しているため、コードの一部を同時に実行できると考えようとする場合があります。あなたの場合、明らかに、そうではありません。ステートメントを順番に実行する必要があるため、そうではありません。同時に実行されません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.