例えば。 Cのような言語で次のように2つの整数を比較する場合:
if (3 > 2) {
// do something
}
3が2より大きい(true)か、そうでない(false)かは、内部でどのように判断されますか?
ウサギの穴をずっと下っていますね。 OKやってみます。
ステップ1. Cから機械語へ
Cコンパイラは比較を 機械語で保存されたオペコード に変換します。機械語は、CPUが命令として解釈する一連の数値です。この場合、「キャリーで減算」と「キャリーの場合はジャンプ」の2つのオペコードがあります。つまり、1つの命令で3から2が減算され、次の命令がオーバーフローしたかどうかを確認します。これらの前に、数値2と3を比較可能な場所にロードする2つの命令が続きます。
MOV AX, 3 ; Store 3 in register AX
MOV BX, 2 ; Store 2 in register BX
SUB AX, BX ; Subtract BX from AX
JC Label ; If the previous operation overflowed, continue processing at memory location "Label"
上記のそれぞれにバイナリ表現があります。たとえば、SUB
のコードは2D
16進数、または00101101
バイナリ。
ステップ2. ALUへのオペコード
ADD
、SUB
、MUL
、DIV
などの算術演算コードは、CPUに組み込まれている ALUまたは算術論理演算ユニット を使用して基本的な整数演算を実行します。数値はいくつかのオペコードによって registers に格納されます。他のオペコードは、ALUを呼び出して、その時点でレジスターに格納されているものすべてについて計算を行うようにチップに指示します。
注:この時点では、Cのように GL を使用する場合にソフトウェアエンジニアが心配することは何もありません。
ステップ3. ALU、半加算器、および全加算器
知っているすべての数学的演算は、一連のNOR演算 に縮小できることを知っていますか?これがまさにALUの動作方法です。
ALUは2進数の処理方法のみを認識しており、OR、NOT、AND、XORなどの論理演算のみを実行できます。バイナリの加算と減算の実装は、 adder と呼ばれるサブシステムで、特定の方法で配置された一連の論理演算で行われます。これらのサブシステムは、2ビットで動作し、それらの単一ビットの合計と単一ビットのキャリーフラグを決定する「半加算器」のネットワークで構成されています。これらを一緒にチェーンすることにより、ALUは8、16、32などのビットを使用して演算を実行できます。
減算はどうですか?減算は、加算のもう1つの形式です。
A - B = A + (-B)
ALUは-B
--B
の 2の補数 を取ります。負に変換されると、値を加算器に送信すると、減算演算が実行されます。
ステップ4:最後のステップ:オンチップトランジスタ
加算器の操作は、「 transitor-transistor logic またはTTL、または [〜#〜 ] cmos [〜#〜] 。いくつかの例については ここ をクリックして、これらがどのように接続されているかを確認してください。
もちろん、チップ上では、これらの「回路」は数百万の導電性および非導電性材料の小さなビットで実装されますが、原理はブレッドボード上のフルサイズのコンポーネントである場合と同じです。 このビデオを見る 電子顕微鏡のレンズを通してマイクロチップ上のすべてのトランジスタを表示します。
いくつかの追加のメモ:
記述したコードは定数のみで構成されているため、実際にはコンパイラーによって事前計算され、実行時に実行されません。
一部のコンパイラーはマシンコードにコンパイルされませんが、Javaバイトコードまたは.NET中間言語など)の別のレイヤーを導入します。しかし、最終的にはすべてがマシン言語を介して実行されます。
一部の数学演算は実際には計算されません。これらは、算術コプロセッシングユニットの大規模なテーブルで検索されるか、ルックアップと計算または補間の組み合わせを含みます。例は 平方根を計算する関数 です。最近のPC CPUには、各CPUコアに浮動小数点コプロセッシングユニットが組み込まれています。