整数比較は内部的にどのように機能しますか?


18

たとえば、Cのような言語で2つの整数を次のように比較する場合:

if (3 > 2) {
    // do something
}

3が2より大きい(true)かそうでない(false)かは、内部でどのように判断されますか?


19
現在の答えは、比較が変数式に関する場合には問題ありませんが、多くの現代のコンパイラがあなたのコードを見て、式が常に真実であることを検出し(リテラルのため)、if完全に無視するという免責事項がありません、コーディングに直行しdo somethingます。
SJuan76


3
@スノーマン私は同意しません。「これがどのように機能するか」というプログラミングの質問は、その質問に要約することができますが、重複することはありません。
user1643723

1
@ user1643723問題の関数が特定のオペコードである場合に実行されます。
クリリス

1
@ user1643723この質問は、コンピューターがどのように基本的な操作を実行するかを尋ねているものであり、一番上の答えは論理ゲートと論理テーブルについて説明しています。デュープターゲットのトップアンサーで広範囲にカバーされている2つのトピックは、あなたの質問にも答えます。

回答:


61

うさぎの穴をずっと下って、え?試してみます。

ステップ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"

上記のそれぞれにはバイナリ表現があります。たとえば、のコードSUB2D16進数または00101101バイナリです。

ステップ2. ALUへのオペコード

算術演算のようなオペコードADDSUBMUL、およびDIV使用して基本的な整数演算を実行するALUまたは論理演算装置は、 CPUに内蔵されて。数は、いくつかのオペコードによってレジスタに保存されます。他のオペコードは、ALUを呼び出して、その時点でレジスターに保存されているものを計算するようにチップに指示します。

注:この時点で、Cのような3GLを使用する場合、ソフトウェアエンジニアが心配することは何もありません。

ステップ3. ALU、半加算器、および全加算器

あなたが知っているすべての数学的操作は、一連のNOR操作に還元できることをご存知ですか?そして、それがまさにALUの仕組みです。

ALUは2進数の操作方法のみを知っており、OR、NOT、AND、XORなどの論理演算のみを実行できます。バイナリの加算と減算の実装は、加算器と呼ばれるサブシステムで、特定の方法で配置された一連の論理演算で実現されます。これらのサブシステムは、2ビットで動作し、1ビットの合計と1ビットのキャリーフラグを決定する「半加算器」のネットワークで構成されています。これらを一緒に連鎖させることにより、ALUは8、16、32などのビットで数値の演算を実行できます。

半加算器

減算はどうですか?減算は、加算のもう1つの形式です。

A - B = A + (-B)

ALU -Bは、の2の補数を取ることにより計算しBます。負に変換されると、加算器に値を送信すると、減算演算が行われます。

ステップ4:最終ステップ:オンチップトランジスタ

加算器の動作は、相互作用して「トランジスターゲート」を作成する電気コンポーネントの組み合わせを使用して実装されます。たとえば、トランジスタートランジスターロジックまたはTTL、またはCMOSにあります。クリックしてここにこれらがアップ配線されているかを確認するためにいくつかの例のために。

もちろん、これらの「回路」は、チップ上に数百万の導電性および非導電性材料の小さなビットで実装されていますが、原理はブレッドボード上のフルサイズのコンポーネントと同じです。 電子顕微鏡のレンズを通してマイクロチップ上のすべてのトランジスタを示すこのビデオをご覧ください。

いくつかの追加のメモ:

  1. あなたが書いたコードは、実際にはコンパイラによって事前に計算され、実行時に実行されません。これは、コードが定数のみで構成されているためです。

  2. 一部のコンパイラは、マシンコードにコンパイルしませんが、Javaバイトコードや.NET中間言語など、さらに別のレイヤーを導入します。しかし、最終的にはすべて機械語で実行されます。

  3. 一部の数学演算は実際には計算されません。それらは、算術コプロセッシングユニットの大規模なテーブルで検索されるか、ルックアップと計算または補間の組み合わせを含みます。例は平方根を計算する関数です。最新のPC CPUには、各CPUコアに浮動小数点コプロセッシングユニットが組み込まれています。


3
TTLを参照するFWIWは、TTLシグナリングを使用する現代のプロセッサはほとんどなく、ほとんどが5v BJTの代わりにCMOS FETと低電圧を使用するため、混乱を招く可能性があります。
-whatsisname

2
@whatsisnameが示唆しているように、CMOSは間違いなくTTLよりも優れたリファレンスになります。最新のプロセッサで実行されるものに対してより正確であるだけでなく、概念的にもはるかに単純だからです。
ジュール

3
@JackAidleyは、この部分の意味です。「つまり、1つの命令で3から2が減算され、次の命令がオーバーフローしたかどうかを確認します。」
KutuluMike

1
つべこべ:私が思うにはCMP、使用されていないことだろうSUB-再びそれである多かれ少なかれ「SUB結果は無視され、唯一のフラグが設定されているwher」
ハーゲン・フォン・Eitzenを

5
半加算および全加算の定義が間違っています。半加算器は2つの1ビット入力を取り、合計とキャリーを返します。全加算器は追加のキャリーイン入力を受け取りますが、それでも1ビットのみです。Nビット加算器を作成するには多くの方法がありますが、最も単純なのは、N個の全加算器のチェーンであるリップルキャリー加算器です。より大きなNの実際には、これはかなり悪い遅延を持っているので、最新のCPU設計ではより複雑な設計が使用されます。
-Voo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.