コンピューターはバイトのデータ型をどのように判断しますか?


31

たとえば、コンピューターが10111100RAMの特定の1バイトに保存されている場合、コンピューターはこのバイトを整数、ASCII文字、または他の何かとして解釈する方法をどのように知るのでしょうか?型データは隣接するバイトに保存されますか?(1バイトに2倍のスペースを使用する結果となるため、これは事実ではないと思います。)

おそらくコンピューターはデータの種類さえ知らず、それを使用するプログラムだけが知っているのではないかと思います。私の推測では、RAMはR AMであり、したがって順次読み取られないため、特定のプログラムは特定のアドレスから情報をフェッチするようにCPUに指示し、プログラムはそれを処理する方法を定義します。これは、型キャストの必要性などのプログラミングに適しているようです。

私は正しい軌道に乗っていますか?


4
補足説明として、型について話している場合は、言語のコンテキストで行う必要があります。そのようなこと(シンボル、チェックタイプ、操作、キャスト、アドレスRAMなど)を処理するのはコンパイラに任されています。CPUとRAMはバイトのみを知っている
ジャン

4
バイトのデータ型はバイトです。それを超えると、コンピューターは何も知りません。プログラムは、バイトまたはバイトのグループを特定のデータ型として解釈し、それらに対して操作を実行しようとしますが、そこに制限はありません。同じバイトのグループは、複数のデータ型として解釈できます(つまり、値型へのポインタのキャスト、Cのような共用体など)。RAMが連続して読み取られないことは、実際には関係ありません。-それは、RAMが汎用であるためです。-たとえば、レジ​​スタも順番に読み取られませんが、入力されます。
BrainSlugs83

5
恥知らずなプラグインですが、この質問は基本的に1か月ほど前にプログラマーSEに尋ねられました。 ここに私の答えがあります。この時点では少し長いですが、いくつかの異なる角度から攻撃します。
シャズ

2
ハードウェアがデータ型に依存しないという事実の1つの有用な結果は、1バイト(または単語など)がプログラムによって複数の方法で解釈できることです。特に、浮動小数点数を整数として一時的に解釈することは、高速逆平方根を計算するために使用されます。
アエウイド

@ BrainSlugs83、それを答えに変換することを検討してもいいですか?
DW

回答:


38

あなたの疑いは正しいです。CPUはデータのセマンティクスを気にしません。ただし、場合によっては違いが生じることもあります。たとえば、一部の算術演算では、引数が意味的に符号付きまたは符号なしの場合に異なる結果が生成されます。その場合、意図した解釈をCPUに伝える必要があります。

彼女のデータを理解するのはプログラマー次第です。CPUは命令に従うだけで、それらの意味や目標を至福に知らない。


1
「引数が意味的に署名または署名されていない場合」について、CPUはどのように知るのでしょうか?CPUオペレーションはパラメータバイトを見るだけで、そのようなデータタイプのコンテキスト認識を欠いています。適切なCPU操作(またはコンパイラー)を選択することにより、データ型を暗示します。
シブ

4
@Shivこのような場合、CPUは実際に、符号なしの数値と符号なしの数値を処理するための異なる命令を発行されます。OPの疑いのように、CPUが認識していないため、プログラムはこれらの詳細を提供する義務があります。
コートアンモン-復活モニカ

2
私は自分自身を覚えている限り、コンピューターで作業してきました。CPUは高レベルのプログラミングで使用する高レベルの構造を気にしないことを知っていても、この概念の分離は時々私を驚かせます
ルーパック

1
@Loupaxまあ、本当に低レベルのアセンブリで作業することはかなり助けになります-たとえmov al, 42高レベルであっても-これが呼び出すことができる命令は1つだけであることは明らかですが、それでもいくらか抽象化されています。ただし、これをmov.8 al, 42明示的に使用すると、これが痛々しいほど明白になります:)
Luaan

1
@Shiv:メモリ内のデータが入力されるマシンがあることに注意してください。これらはタグ付きメモリアーキテクチャ(または単にタグ付きアーキテクチャ)と呼ばれますが、アセンブリではなくコンパイルされた言語で主にプログラムし、コンパイラが入力を処理するため、通常のアーキテクチャほど商業的に成功していません。参照:en.wikipedia.org/wiki/Tagged_architecture
slebetman

14

他の人がすでに答えているように、今日の一般的なCPUは、特定のメモリ位置に含まれるものを知りません。ソフトウェアが決定します。

ただし、他の可能性もあります。たとえば、Lisp Machinesは、各メモリ位置のタイプを保存するタグ付きアーキテクチャを使用しました。そうすれば、ハードウェア自体が高水準言語の作業の一部を実行できます。

そして今でも、Intel、AMD、ARM、およびその他のアーキテクチャのNXビットは同じ原則に従うと考えられると思います。特定のメモリゾーンにデータまたは命令が含まれているかどうかをハードウェアレベルで区別します。

また、完全を期すために、ハーバードアーキテクチャ(一部のマイクロコントローラーなど)では、データと命令は物理的に分離されているため、CPUは読み取り内容をある程度把握しています。

このQuoraの質問には、タグ付けされたメモリがどのように機能したか、パフォーマンスへの影響と終miseなどに関するコメントがあります。


タグ付きアーキテクチャは興味深いメモです。それはかなり速いでしょうか?
バシネーター


3

型注釈はありません。
RAMは純粋なデータを保存し、プログラムは何をすべきかを定義します。

CPUレジスタを使用すると、特定のタイプ(FPUなど)のレジスタがある場合、内部が何であるかがわかります。
浮動小数点レジスターの操作は、明示的に型付きデータを使用しています。あなたまたはあなたのコンパイラは、いつどこに配置すべきかを指示するので、そのような自由はありません。
コンピューターは、R​​AM内のデータと、1つの例外を除いてレジスター内の基礎データについては何も想定していません。これは、データが期待されるタイプである場所があることを示すためだけですが、文字列をフロートにキャストして乗算することを妨げるものは何もありません。

プログラミング言語ではタイプを指定します。または、より高レベルの言語ではデータは一般的であり、コンパイラー/インタープリター/ VMは内部にオーバーヘッドをエンコードします。
たとえば、Cの場合、ポインター型はデータの処理方法、アクセス方法を示します。

もちろん、文字列(文字)を読み取り、浮動小数点値、整数として扱い、それらを混合することができます。


FPUレジスタのビットでさえ、常に浮動小数点値を表すとは限りません。昔(もう多分そうではないでしょうか?)、一般的な最適化は、浮動小数点レジスタ(64ビット以上)を使用して、汎用/整数レジスタ(32ビット)よりも高速にデータをコピーすることでした。通常、データを2倍の速さでコピーできました。
セス

1
私はあなたに完全に同意します。だから誰かがそこに文字列をプッシュするかもしれないと書いたのです。同時に、人々は整数に対して浮動小数点演算を行いました。それは高速だったからです。そこが肝心だ!

@HCBPshenanigansには、浮動小数点値を操作する命令があります。FADDを使用する場合は、(4、8、または10)バイトのメモリグループが浮動小数点数を保持しているという意味のみです。これは、いくつかの種類の命令に当てはまります。2つの整数を乗算するのは、整数の場合にのみ意味があり、ジャンプはアドレスの場合にのみ意味があります。
JDługosz

@sethおよびevilJSは、レガシーの浮動小数点スタック8087命令の場合とは想定されていませんが、解釈なしでロード/保存するためだけに使用できる新しいCIMDレジスタの場合です(整列する必要がありますが) CIMDレジスタがされた場合に決して彼らはコンテキストスイッチに保存する必要はありませんよりも、使用されません。XMMレジスタを介して(のみ)8バイトを移動する場合、セット全体を保存する必要があるため、これは正味の損失です。
JDługosz

3

CPUは気にせず、アセンブリコードを実行しますが、これは単にデータを移動、シフト、追加、または乗算するだけです...

データ型は、より高いレベルの言語の概念です。CまたはC ++では、操作するすべてのデータに対して型を指定する必要があります。C / C ++コンパイラは、これらのデータをCPUが処理する適切なコマンドに変換します(コンパイラはアセンブリコードを記述します)

さらに高いレベルの言語では、Typesが推論される場合があります。たとえば、PythonまたはJavascriptでは、データ型を指定する必要はありませんが、データには型があり、整数で文字列を追加することはできませんが、追加することはできます整数を持つフロート:「コンパイラー」(Javascriptの場合はJIT(Just in Time)コンパイラーです。Javascriptは、歴史的にブラウザーがJavascriptコードを解釈するため、「解釈済み」言語と呼ばれますが、最近のJavascriptエンジンはコンパイラーです。

コードは常にマシンコードにコンパイルされますが、明らかにマシンコードの形式はターゲットとするマシンによって異なります(x86 64ビットコードはx86 32ビットマシンやARMプロセッサでは動作しません)

そのため、インタープリターコードの実行には、実際には多くのレイヤーが関係しています。

JavaまたはC#コードは技術的にはJavaバイナリ(バイトコード)に「コンパイル」されるため、JavaとC#も興味深いものですが、そのコード自体はJavaランタイムによって解釈されます。 Javaバイナリ(Jars)を実行する適切なマシンをターゲットとするJRE


コンパイラは、JITであろうとなかろうと、コンパイルします。インタープリターはコンパイルせずに解釈します(そうでない場合はコンパイラーになるためです!)。それらは非常に異なるものです。また、バイトコードの解釈が原因で「Javaがおかしい」ことについては、x86マシンコードでさえ、マイクロプロセッサによってマイクロコードに実際に解釈される(またはコンパイルされる)ことを考慮してください。
hmijail

説明をありがとう...合意:コンパイラがコンパイルし、インタプリタが解釈します。Javascriptの場合、一部の古いブラウザーはコードを解釈するため、ストーリーは少し複雑ですが、最新のブラウザーは実際にジャストインタイムでコンパイルされるため、おそらく「解釈された」言語と呼ばれています技術的にはもうありません。
MrE

しかし、私の知る限り、JSは解釈を開始し、必要に応じてコンパイルされる可能性があります。また、多くのことに応じて、JITは解釈済みからコンパイル済みに、そして再び解釈済みに切り替えることができます。たとえば、特定のタイプの変数に対してコードがコンパイルされる場合があります。しかし、その後、別のタイプの変数でコードが再度実行されるため、既存のコンパイル済みコードを使用できないため、インタープリターがジャンプします
...-hmijail

あなたは私が言わなかったものを引用していますが、それは完全に間違っているので削除してください。マイクロコードはOSとは関係ありません。それはマイクロプロセッサの内部にあるものです。32ビットまたは64ビットもそれとは何の関係もありません。
hmijail

3

データ型はハードウェア機能ではありません。CPUはいくつかの(多くの)異なるコマンドを知っています。これらは、CPUの命令セットと呼ばれます。

最もよく知られているものの1つはx86命令セットです。このページで「乗算」を検索すると、50件の結果が得られます。MULPDそしてMULSD、倍数の乗算の場合 FIMUL、整数の乗算の場合、...

これらのコマンドはレジスターで機能します。レジスタは、これらのビットが何を表すかに関係なく、固定数のビット(CPUが使用するアーキテクチャに応じて32または64の場合が多い)を含むことができるメモリスロットです。したがって、CPU命令はレジスタの値を異なる方法で解釈しますが、値自体には型がありません。

スチュアート・ウィリアムズがPyCon 2017で例を挙げました:

ここに画像の説明を入力してください


1
これは厳密には真実ではないことに注意してください:任意の値を含めることができない特殊なレジスタがあります(たとえば、アドレスではなく、任意の追加を許可しないポインタレジスタ、または可能なレジスタ「正規化されていない値を保存しない」。しかし、ほとんどのアーキテクチャの汎用レジスターの答えは正しいです。
ジル「SO-悪であるのをやめる」

2

...特定のプログラムがCPUに特定のアドレスから情報を取得するように指示するだけで、プログラムはその処理方法を定義します。

まさに。しかし、RAMは「シーケンシャル」に読み取られるわけではなく、ランダムアクセスメモリの略であり、まったく逆です。

バイト何であるかを知る以外に、それがbyteであるか、浮動小数点数のような大きなアイテムのフラグメントであるかさえ知りません。

特定の例をいくつか挙げて、他の回答に追加したいと思います。

検討してください01000001。プログラムは、その意味に関係なく、データの大部分の一部として、ある場所から別の場所にコピーする場合があります。しかし、それをテキストモードのビデオバッファで使用されるアドレスにコピーすると、文字Aが画面上の特定の位置に表示されます。カードがCGAグラフィックモードの場合、まったく同じアクションで、赤いピクセルと青いピクセルが表示されます。

レジスタでは、整数としての数値65が可能です。32のビットを設定するために算術を行うことは、コンテキストのないものを意味する可能性がありますが、具体的には文字を小文字に変更する場合があります。

8086 CPUは(まだ)と呼ばれる特別な指示があるDAA あなたはちょうどあなたが2桁として解釈される命令を使用している場合は、レジスタは2桁を保持しているときに使用されます41

メモリワードは、何か他のものがそこに格納されているときのポインタであると考えて読み取られるため、プログラムがクラッシュします。

デバッガを使用して、メモリ、マップを検査しますを使用して表示の解釈をガイドします。このシンボル情報がなければ、低レベルデバッガーで次を指定できます。このアドレスを16ビットワードとして表示し、このアドレスを長い浮動小数点として、文字列として...何でも表示します。ネットワークパケットダンプまたは不明なファイル形式を見ると、それを解決するのは困難です。

それは、現代のコンピューターアーキテクチャにおける力と柔軟性の主要な供給源です。メモリセルは、値で何をするか、そしてそれが後続の操作にどのように影響するかによって、プログラムにとって「意味する」ことだけを暗示する、あらゆるデータ、命令を意味します。 意味は整数の幅よりも深いです:これらの文字は... asciiまたはebcdicの文字ですか?英語またはSQUの製品コードで単語を形成しますか?送信先アドレスまたは送信元アドレス 最下位レベルの解釈(論理ビット、整数のような、符号付きまたは符号なし、浮動小数点、bcd、ポインタ)は、命令セットレベルではコンテキストに依存しますが、すべてのレベルですべてのコンテキストであることがわかります。住所は、封筒に印刷されている場所のためです。CPUではなく、郵便配達員のルールに応じて異なります。コンテキストは1つの大きな連続体であり、その一端にビットがあります。


※脚注:DAA命令はbyteとしてエンコードされます00100111。したがって、そのバイトは、命令ストリームで読み取られた場合は前述の命令であり、27bcd数字として解釈される場合は数字、0x27 = 39 はASCII の数字9である整数、および割り込みテーブルの一部(INT 13の半分) BIOSサービスルーチンに使用される2バイトアドレス。


1

メモリ位置が命令であることをコンピューターが認識する唯一の方法は、命令ポインターと呼ばれる専用レジスターが何らかの点でそれらを指すことです。命令ポインタがメモリワードを指す場合、命令としてロードされます。それ以外に、コンピューターにはプログラムと他の種類のデータの違いを知る方法がありません。

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