バイナリ/ 16進数からアセンブリ命令セットにどのように移行しますか?


13

だから私は最近ここで少しの間組み込み/アセンブリのプログラミングを学ぼうとしていますし、最低レベル(ゲートなど)を学ぼうとしています。

しかし、私を困惑させるのは、命令セットを「取得」する方法です。ゲート/ TTLなどがどのように機能するかはある程度理解していますが、そこからmov、add、clrなどにどのように到達するのかわかりませんか?

それはおそらくばかげた質問でしょう。...しかし、私は最初のマイクロプロセッサ/コントローラに戻って考え、そして....彼らが命令セットをどのように正確に設計し、それを機能させたのでしょうか?

編集:私はクラリティのために、最初のマイクロプロセッサについて話しているふりをしていると思います、彼らはどのようにバイナリから実際に命令セットを作成するのですか?


2
すべての命令には値があり、コンパイラはコードの構造に基づいてコードをこれらの命令に変換します。
ラムハウンド

1
私は完全にあなたの質問を理解している場合、私はわからないんだけど、私はあなたの答えを見つけることができると思い、ここでここここ
e-MEE


3
彼らはどのようにバイナリから実際に命令セットを作成しましたか? 実際、「彼ら」はそうではありませんでした-少なくとも一般的には逆です。CPUデザイナーは、CPUが実行する操作を決定し、それから命令セットを作成し、命令(ニーモニック)をオペコード(バイナリマシンコード)にマップします。@Scott Whitlockは以下の良い答えを提供しました。少なくとも私の経験では、あなたの仮定は逆向きなので、あなたの質問の最後の部分に対処したかっただけです。
ラジアン

1
この本当に素晴らしい本:www1.idc.ac.il/tecsは私にすべてを説明したものであり、ほとんどの章はオンラインで無料で入手できます。nandゲート、次にアセンブラー、コンパイラーから独自のチップを(単純なハードウェア記述言語で)設計し、作成した言語でosを記述します!素晴らしいもので、com学位のない人としては、私にとっては十分に時間を費やしました!
-bplus

回答:


18

CPUの心臓部はALUです。事前定義された一連の2進数である命令(MOVなど)を取得し、0、1、または2のオペランドを取得し、それらに対して適切な操作を実行します。最も単純な命令は、基本的に何もしないNOP(操作なし)である可能性があります。別の典型的な操作はADD(2つの値を追加)です。

ALUは、「レジスタ」との間でデータを読み書きします。これらは、CPU内部の小さなメモリ位置です。命令の一部(使用するレジスタの数に応じて各入力に2〜3ビット)は、どのレジスタから読み込むかを示します。ALUの外部のCPUには、必要なデータ(および命令)をメモリからレジスタにロードし、レジスタから結果をメモリに書き戻す処理を行うユニットがあります。結果を書き込む場所も、別の2または3ビットにエンコードされます。

操作を表す2進数である「opコード」の選択は任意ではありません。適切に選択されたオペコードは、ALUの複雑さを軽減します。各ビットまたはビットのグループは、ALUの特定の論理ゲートを有効または無効にする傾向があります。たとえば、ADD命令では、出力ステージで内部加算ロジックの結果を選択できるようにする必要があります。同様に、MUL命令は乗算ロジックの結果を選択します。設計によっては、加算回路と乗算回路の両方が実際に入力オペランドに対して演算を実行する可能性が高く、変更されるのは出力選択(ALUの出力ビットに書き込まれるもの)だけです。


1
私は何を求めていると思いますか、彼らはどのように選ぶのですか?そして、彼らはそれを実際にどのように割り当てますか?

1
@サウロン:3番目の段落を再度読み、バイナリ算術演算とデジタル回路を理解してください。デジタル回路の8ビットラインで256命令の命令セットを表すことができます。つまり、可能性のあるすべての状態を転送するには、ハードウェアデバイスに8つのioポートが必要です(1行に2つの状態^ 8行= 256の可能な状態)。処理ユニットは、そのデジタル入力信号をどうするかを決定できます。デジタル回路とは、HiとLo、電圧または電圧なしの2つのハードウェア状態があることを意味します。それがバイナリの由来です。バイナリ表現は、金属に最も近い表現です。
ファルコン

3
@Sauron- デジタルマルチプレクサーを調べて、デジタル回路が複数の値のいずれかから選択する方法を確認します。8ビットバスを使用している場合、これらのバイナリデジタルマルチプレクサーのうち8つが並列に必要です。
スコットホイットロック

1
@Falcon Ok .......それはもっと理にかなっていると思う。最終的にはすべてバイナリ信号になります...そして「mov」などの命令でさえバイナリとして表されることを忘れてしまいます。

1
@Sauron-CPUについて調べてください。これは、オペコードとは何か、どのように機能するかを理解するのに役立ちます。特定のオペコードが選択される理由は重要ではありません。「なぜ」の質問をしても、あまり意味がありません。それらがどのように選択されるかを理解すると、CPUとその構造についてさらに理解するのに役立ちます。
ラムハウンド

9

私はあなたの質問を文字通り受け止め、一般的なコンピューターではなく、ほとんどマイクロプロセッサーについて議論します。

すべてのコンピューターには、ある種のマシンコードがあります。命令は、オペコードと1つ以上のオペランドで構成されます。たとえば、Intel 4004(最初のマイクロプロセッサ)のADD命令は1000RRRRとしてエンコードされました。1000はADDのオペコードで、RRRRはレジスタ番号0〜15(バイナリで0000〜1111)を表します。

16個の4ビットレジスタ(INC、ISZ、LD、SUB、XCHGなど)のいずれかを参照する他のすべての命令も、下位4ビットを使用してレジスタ番号をエンコードし、上位4ビットのさまざまなエンコードを指定して指定しますオペコード。たとえば、ADD、SUB、LD、およびXCHGは、レジスタフィールドと組み合わされたオペコード1000、1001、1010、および1011(すべてバイナリ)を使用します。そのため、ロジックを簡素化するためにパターンがどのように使用されるかを確認できます。

最初のコンピュータープログラムは手書きで記述され、1と0を手動でエンコードして、機械語でプログラムを作成しました。これは、ROM(読み取り専用メモリ)にプログラムされました。現在、プログラムは一般に、マイクロコントローラーの場合は電気的に消去可能なフラッシュメモリに書き込まれ、マイクロプロセッサーの場合はRAMを使い果たします。(後者はまだブートのためにある種の読み取り専用メモリを必要とします。)

機械語は非常に速く退屈になるため、ニーモニックアセンブラー言語を使用して、通常は命令ごとに1行のアセンブリコードを機械語に変換するアセンブラープログラムが開発されました。したがって、10000001の代わりに、ADD R1と記述します。

しかし、最初のアセンブラーはマシンコードで作成する必要がありました。その後、独自のアセンブラコードで書き換えることができ、マシン言語バージョンが最初にアセンブラコードをアセンブルするために使用されました。その後、プログラムはそれ自体を組み立てることができます(これはブートストラップと呼ばれます)。

最初のマイクロプロセッサはメインフレームとミニコンピューターが登場してからずっと後に開発され、4004はアセンブラーの実行にはあまり適していないため、Intelはおそらくその大型コンピューターの1つで実行されるクロスアセンブラーを作成し、 ROMにプログラムできる4004をバイナリイメージに変換します。


4

非常に低いレベルのコンピューターは、データパスコントロールで表すことができます。これらを一緒にグーグルすると、デジタルアーキテクチャ/デザインの基本であるため、多くの読み物が得られます。

要約するために最善を尽くします:

ここで述べたように、中心にはALUがあります。ALU(およびCPUの他の部分)について知っておく必要があるのは、異なる操作に合わせて再構成できることです。具体的には、データパスを再構成する機能があります。これは、パラメーターの取得方法、実行する操作、およびパラメーターの保存場所です。これら3つのことを操作できることを想像してください。これが私たちのコントロールです。

それでは、どのようにこれを達成するのでしょうか?既に述べたように、低レベルのデジタルロジックを利用して、さまざまなパスにマルチプレクサを作成できます。マルチプレクサは、入力用のビットのセットを使用して制御されます-これらのビットはどこから取得されますか?命令自体からエンコードされます。要点:mov、addなどの命令は、特定の操作用にデータパスを構成する方法をCPUに指示するビットのセットにすぎません。読んでいるもの(mov、add)は人間が読める形式(アセンブリ言語)であり、プログラムはデータパスと操作の手順を定義しています。

これが、この分野でより知識のある人にとって、より複雑なプロセスを単純化しすぎていることをおIびします。参考までに、電気工学スタック交換は非常に低レベルのロジックを扱うため、この質問をするのに最適な場所です。


3

あなたの質問を理解しても、ビン/ヘックスまたはアセンブリがどのように関連しているか理解できません。

あなたの質問の要点は、移動、ロード、保存、追加などの指示ではなく、基本的なゲートからどのように取得するかであると仮定します。

基本的なゲートやそのようなhttp://github.com/dwelch67/lsasimから加算と減算がどのように機能するかについての詳細の一部を含む、ゼロから作成した独自の小さな指導命令セットがあります

PetzoldのCode(何か何か)の本を探してください。エレメンタリーへの道を始めるかもしれませんが、コンピューターや電子機器とは何の関係もない状態から、バイナリー、ヘックス、基本ゲートなどにゆっくりと進みます。

今日、ゼロから構築する方法について尋ねていますか?今日は、命令セットの定義から始めます。あなたはただ座ってそれを書き、ロードとストア、ムーブとaluのものを持たなければならない命令の種類を考え、そしてレジスタの数、レジスタの大きさ、これは命令のサイズに部分的に影響します命令サイズについて...

停止して、どのようにプログラムを書くのか聞いてみましょう。テキストエディタの空白の画面から始めますか?必要な変数、関数、プログラミング言語などを解決しようとしているタスクについてある程度の考えがあります。また、それぞれの人は異なりますが、ある程度これを行います(関数の定義と作成など)。その一部(再利用可能な定義と列挙、構造体などを使用してヘッダーファイルを作成する)、およびその他のこと(コードだけ、関数に変数とコードを入力する)。そして、さまざまなタスクを循環させ、最終的にはコードサイズ、速度、読みやすさ、品質、機能などのバランスが取れていると感じます。ハードウェア設計と違いはありません。ハードウェア設計者はプログラミング言語(vhdl、verilog)も使用し、同じプロセスを実行します。

ソフトウェアプログラムを思いつくのと同じように、欲求、パフォーマンス、サイズ、機能などのバランスをとります。必要なデザインルールや、上司があなたに作らせたデザインルールなどが必要になる場合があります。初期設計から実装まで、いくつかの大きな間違いがあり、初期設計に戻って命令セットを変更する必要があることがわかります。コンパイラーとシミュレートされたプロセッサーがあれば、コンパイルされたコードの品質、パフォーマンスなどを劇的に改善するいくつかの特定の命令が本当に必要であることがわかります。

したがって、いくつかの命令セットをゼロから考案し、ハードウェア設計の経験を活用して、同様のビットパターンを持つ同様の命令をグループ化することで、ハードウェア言語プログラミングだけでなく、電力とゲートの節約など、より簡単にデコードできるようになりました良いもの。最近、ある種のシミュレータを作成します。私の理解では、ARMは最初にソフトウェアシミュレータであり、その後ハードウェア設計が登場しました。それが真実かどうかはわかりませんが、その話に固執しています。これはチームに依存します。一部のチームは単なるハードウェアであり、HDLでのプログラミングに専念したい場合があります。私のように、両方を少しやりたい場合もあります。最近では、優れたハードウェア言語シミュレータが利用できるため、コンパイルおよびシミュレーションするハードウェアを構築する必要はなく、ハードウェアシミュレーションプログラム/パッケージを使用してデバッグの多くを行う必要はありません。ソフトウェアチームは、命令セット用のアセンブラーとコンパイラーを開発し、シミュレートされたramおよびromフィードプログラムをシミュレートされたプロセッサーに使用して、そのペースを試してみることができます。私が取り組んでいたプロセッサでフルLinuxブートをシミュレートしましたが、何時間もかかりましたが、動作しました(そのようにロジックにキャッシュバグが見つかりました)。

だから今、私はあなたが本当に求めていたと思うものについて。命令セットを使用して、基本的なゲートからプロセッサにどのようにアクセスしますか。基本的なゲートAND、OR、NOTは本当にアナログであり、時間の概念がありません。入力の電圧を即座に変更することはできず、その電圧を変更すると出力が変化し始めます。ゲートはトランジスタで構成され、トランジスタは増幅器であり、入力にそれをある数で掛けて、反対側にその電流を流します。それらを論理ゲートとして使用する場合、実際にはそれらを過飽和状態にしています。入力電圧が非常に高いか低いため、トランジスタは最大電圧しか駆動できないか、電圧(電流)を駆動できません。基本的に、トランジットはスイッチに変わります。要するに、時間という概念はありません。命令セットを設定するには、プログラムを順番に処理するために命令を発生させる必要があり、現在この命令を使用しているという概念を持たなければならず、次の時間枠でその命令を処理します。アンプをスイッチに変えるゲームと同じように、基本的な論理ゲートとクロックを使用して同様のゲームをプレイします。クロックは、一定のレートでオン/オフする電圧を発生させる缶の中の魔法の結晶から発生します(ここで説明する価値はありません)。論理方程式でその電圧を使用すると、シーケンスを開始できます。クロックは、一定のレートでオン/オフする電圧を発生させる缶の中の魔法の結晶から発生します(ここで説明する価値はありません)。論理方程式でその電圧を使用すると、シーケンスを開始できます。クロックは、一定のレートでオン/オフする電圧を発生させる缶の中の魔法の結晶から発生します(ここで説明する価値はありません)。論理方程式でその電圧を使用すると、シーケンスを開始できます。

この真理値表についてごく簡単に考えてみましょう。

0 0 0
0 1 1
1 0 1
1 1 0

バイナリで:

0 + 0 = 1
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10 (2 decimal)

1ビット加算器であるlsbitのみに注目すると、上記の真理値表は1ビット加算器について説明しています。また、XORゲートについても説明します。一方の入力が真か、もう一方が両方ではありません。

複数のビットを取得するには、キャリービットのキャリーインとキャリーアウトを調べる必要があり、3ビット加算器、2つのオペランド、キャリーインと2つの出力、キャリーアウトと結果ビットが必要です。3入力2出力の加算器ができたら、必要なだけカスケード接続できます。しかし、これはまだアナログであり、ゲートは即座に変化します。

このアナログ加算器をADD命令に変換する方法は、配置したこれらのゲートへの入力として存在する命令を調べるロジックがある場合です。命令の一部のビットは、これが加算命令であり、一部のビットは、1つのオペランドがそのようなレジスタであり、レジスタ7である可能性があると言い、他のビットは、他のオペランドがレジスタ4であると言うことがあり、アーキテクチャに応じて結果をレジスタ2に入れるという命令で定義された別のレジスタがあります。レジスタ7の内容をalu加算器の1つの入力にルーティングし、レジスタ4の入力を加算器にルーティングし、レジスタ2への加算器の出力。クロックはこのロジックの一部であるため、クロック周期の開始から次のクロック周期の開始までの期間があり、すべてのアナログ信号が落ち着き、配線されている論理式を解決します。ライトスイッチを切り替えるときとは異なり、ライトの状態をオフからオンに変更します。そのライトがウォームアップし、基本的に定常状態になるまでには時間がかかります。ここではそれほど違いはありません。

このクロック周期がAND命令の実行フェーズである場合、次のクロック周期で結果を出力レジスタに保存するなどのことを言うロジックがあります。同時に、次の命令などをフェッチします。したがって、ALUの実行が1クロック周期であることが多い現代のプロセッサでは、アナログロジックが高速に論理方程式を解決できるためです。数にカウントする必要のある古いプロセッサは、加算器を配線したままにし、加算器ロジックが解決するまでxクロックサイクル待機してから、出力から結果をサンプリングし、aluの異なる入力をフィードし、xクロックサイクル待機します解決するには、永久に、または電源が切れるまで繰り返します。

論理方程式とはどういう意味ですか?それだけで、必要に応じてAND、OR、NOTゲートの観点から考えることができます。alu加算回路への各入力ビットには、現在の命令を含むフリップフロップ(個別/単一メモリビット)を含むクロックを含む非常に長い方程式(およびそれらのそれぞれに供給する方程式)があります。メモリビット)とオンとオン。これが入力を受け取り、タスクを実行し、終了して結果を返す関数であると仮定して、記述した言語で記述した単一のソフトウェア関数を使用します。入力の考えられるすべての組み合わせと、その関数を通るさまざまな実行パスを考えてください。いくつかの高級言語で書いたかもしれませんが、おそらくその言語でさえ、多くの入れ子になったif-then-else構造を使用して、より原始的でより原始的なものに書き換えることができます。そして、おそらくアセンブリ言語に下って行きます。私が話している方程式とは異なり、ハードウェアプログラマーは、選択したプログラミング言語がその多くを保存する場合、おそらくアセンブリ言語での長い曲がりのif-then-elseツリーでプログラムするよりも、これらの長い曲がりくねった方程式でプログラミングしません。使用するコンパイラが小さなソースコードを大量のif-then-elsesを持つ長いワインドアセンブリに変換するように、ハードウェアプログラミング言語コードを取得して論理式に変換するコンパイラがあります。

さて、最初のCPUに戻ります(今日はマイクロコントローラーを検討しますが、それはCPUでした)。上記のすべてを紙で行い、実際に論理式を書いたハードウェアプログラミング言語を使用しませんでしたが、命令のビットパターンを選択して、ゲートの数とそれらのゲートを接続するワイヤを単純にする実用的。紙では、手作業で配線された論理ゲートの長いリストを作成し、その後、シリコンマスクの拡大版に実際のコンポーネントを描画する必要がありました。今日でも、チップは素人向けの写真やシルクスクリーンのようなプロセスを使用して行われているので、必要に応じてこれらの青写真を撮り、シリコン層に縮小して適用します。

ここでも、アセンブリの処理が改善され、テキストエディタや最初のプログラムを紙で書かなければならないアセンブラを持っていなかったアセンブリプログラミングを行うだけでなく、リファレンスマニュアルを使用して、手動で1と0のマシンコードに変換しました。それらのコンピューターの一部では、スイッチを反転してRAMをロードし、アドレスビットを反転し、データビットを用紙上の数字と一致するまで反転し、クロックビットを上下に反転して、1つのメモリー位置をロードしなければならなかったかもしれませんプログラムの1つの命令の1バイトを数百回繰り返し、間違いを犯さないことを望みます。

最初のCコンパイラが他の言語で書かれたと思われるのと同じように、Cで書き直され、最初のCコンパイラでコンパイルされ、それから再び自分自身でコンパイルされることにより、セルフホスティングになりました。その後、Cコンパイラを使用して他のプログラミング言語を発明し、それがセルフホスティングになりました。私たちは自分自身の上に構築されたオペレーティングシステムとテキストエディタを発明しました、そして、それはすべて黒魔術です。

はい、非常に長い間、それは真の把握のために何年もの研究と経験を必要とする大きな質問です。私のlsasimを見て、私は何かの専門家であると主張してはいけませんが、それは命令セットであり、Cで書かれた命令を実行するシミュレータと、ハードウェアプログラミング言語で実装されたプロセッサの別の実装の両方がありますさまざまなツールを使用してシミュレート。さらに、粗雑なアセンブラと他のツールなどがあります。おそらく、これのいくつか、特にハードウェアプログラミング言語のコードを調べることによって、あなたが求めていたと思われるもののギャップを埋めることができるかもしれません。そのギャップを閉じていない場合、または長い巻き線を作った場合は、この答えを削除することを教えてください(プログラマーの交換でたむろすることはできないと想定しています)。


これは実際には著者の質問には答えず、少なくとも議論には何も加えず、受け入れられた答えがカバーしなかった。あなたのバイナリ数学は100%正しくありません1 + 1は0のオーバーフローで0です。レジストリのサイズに応じて、2または0になります
。-ラムハウンド

@dwelchくそ!私はあなたの死ぬ心のファンです。+1
AceofSpades

2

CPUは0と1で動作します。すべての命令には、それらを定義する一連のビットがありました。Thsiはマシンコードでした。人間にとって読み書きが難しい。最初のステップとして、0と1を4ビットシーケンスにグループ化し、0からFを使用してそれらを表現しました。これにより、記憶しなければならない数字は減りましたが、それでも命令の16進コードを覚えるのは容易ではありませんでした。

そこで、MOVやADDなどの「単語」を含むアセンブリを使用し始めました。アセンブラは、命令を0 'および1'の正しいセットに置き換え、アセンブリの「リスト」をマシンコードに変換します。

最終的に、「命令」がマシンコードのシーケンス全体を表す「高」レベルの言語を開発しました。


参考までに、8進数は16進数の前に2進数の速記として使用されました。
オコド

Slomojoは正しい、オクタル、ベース8は3ビットを使用し、16進数、ベース16は4ビットを使用しました。Octalには、0から7までの数字が何であるかを全員が知っているという利点がありました。六角を使用していませんでしたどのように人々はしばしば「数字」F.へAによって当惑された
ジム・C

0

私は最近このQ / Aに出会い、約1年前にこの道を歩き始めました。これは、私自身の関連する質問に関して、非常に優れたリソースおよびリファレンスページであることがわかりました。


パート1:- はじめに-

私自身について少し:

私がまだ小学校にいた80年代半ばから後半にかけて、50年代から80年代までのジャンクステレオ、VCR、およびその他の電子デバイスを分解し、回路基板を見て、どのようにそれらが行われたかを常に知りたいと考えていました仕事...彼らはどのようにして実際に放送信号を取得し、オーディオ、ビデオを生成し、これを行いましたか...彼らがそのような若い年齢で何をしたか、どのように機能したかを知ってください。

長年にわたり、私は数学、物理学、化学の分野で常に例外的でした。私は数学を高度に理解し、中学や高校時代の簡単なまたは基本的な回路を読むことさえできましたが、論理ゲートとその構築方法について学ぶことはできませんでした...しかし、私はしました高校の論理代数、確率、統計学の名誉クラスからブール代数を学びます。私の数学と科学の授業はすべて優等授業でした。コミュニティカレッジの2学期までは、Calculusを受講しませんでした。私は大学代数をテストし、三角法を復習コースとして取りました。教室での私の最高レベルの数学は、単一変数の微積分IIです。

私は3歳か4歳の頃からビデオゲームをしていました。子供の頃、私はアタリ、NES、セガジェネシス、PS1を持っていました。年を取り、10代後半から20代前半になって、PS2とSNESを好みのタイトルで取得しました。これは、Doom!にまで遡るPCゲームも考慮していません。

私は常に熱心なコンソールおよびPCゲーマーであり、これにはピンボールゲームやアーケードゲームは含まれません。

90年代初頭のクリスマスに12歳だったときに、最初のPCを受け取りました。DOS 6.0およびWin 3.11またはOS / 2の時代。それ以来、私は常に「Windows」ファミリのオペレーティングシステムに精通しており、私が持っていたシステムはすべてIntelアーキテクチャでした。学校や大学のAppleやMacでの経験は限られていますが、Linuxシステムで作業する特権はありませんでした。私にはCygwinがあり、bashの学習に挑戦しましたが、Dosやコマンドプロンプトの構文には非常に慣れています。

90年代前半には、PC-Worldを1つか2つ手に入れ、よく知らないQBasicにコードスニペットを入力し、それらのプログラムを機能させようとしました。唯一成功したのは、ホームキーのキーを押して別の着信音にするプログラムです。携帯電話の着信音を意味するのではなく、キーを押し続けている限り連続した周波数を意味します。

電子機器がデジタルおよび論理レベルで回路内でどのように機能したかを知りたいだけでなく、コンピューターのプログラミング方法を学びたいだけでなく、自分のビデオを作りたいという欲求が常にありました。ゲーム。90年代前半にも、フロッガーとテトリスのゲームを作りたかったのですが...


これが、コンピューターサイエンスの分野で最もタフなプログラミングまたはソフトウェア開発の1つ、つまり3Dゲームエンジンデザインに取り組む私の主な動機と欲求になりました。コンピューターサイエンスには他にも厳しい分野がありますが、個々のコンポーネントやサブエンジンがその技術や特性を必要とするため、洗練されたゲームエンジンには通常またはほとんどすべてが含まれます。

私は高校時代からプログラミングの経験がありましたが、これは恐ろしいVisual Basicに限定されていました。私は、1999年に高校を卒業してから数年後まで、2002年から2003年頃にC / C ++を習得し始めました。献身と決意、私はコンピュータ、ハードウェア、プログラミング、アルゴリズムなどに関してはあらゆる概念について学びましたが、私はできる限り多くを学び続けています...

C / C ++を習得した初期の頃は、インターネットにアクセスできましたが、インターネットは初期段階にあり、Amazon、Youtube、FacebookなどのWebサイトはまだ存在していませんでした。 2番目の専用回線がない場合、電話回線を使い切るモデムをダイヤルアップします。画像が画面にレンダリングされるのに数分しかかかりません。連続したビデオ再生を気にしないでください。

そのため、C ++でのプログラミング方法の調査と学習に関しては、リソースは限られており、ほとんどはテキスト形式でした。初期のインターネットチュートリアルの日からプロジェクトに取り組もうとしたとき、それらのプロジェクトの多くは完全に完成していませんでした。 、リンクおよびデバッグ、ライブラリ統合。

それらのトピックについて何も知らない人にとっては、何が間違っていたのか、それを修正する方法、それを適切に機能させる方法がわからないため、彼らは途方に暮れています。当時、リソースが非常に限られていたため、試行錯誤に何時間もかかりました。このウェブサイトでできるように助けを求めたり、cppreferenceで見つけることができる詳細な説明を探したりすることはできませんでした!あなたが個人的に誰も知らなかった場合、あなたは援助のために頼ることができるほど多くはありませんでした!

時間が経つにつれて、私はどこかで私の知識の一部を改善し、最終的にインターネットはDSLに改善されました。 Youtubeが現れ始め、研究面で物事が少し楽になったように。ますます多くのチュートリアルがすぐに利用できるようになりました。他の人が悪い習慣を教えたのに対して、いくつかは良いと便利でした...

また、開発に必要なツールを見つけて入手するのに多くの時間を費やしていました。言語の構文、コンパイラ、コンパイルプロセス、リンク、構築、デバッグを学ぶ必要がありました。次に、利用可能なさまざまなライブラリとAPI、およびそれらの依存関係をすべてリンクするようにプロジェクトまたはソリューションを構成する方法について学習する必要がありました。

長年にわたって、私はC ++言語が時間とともに成長、進化、適応するのを見てきました。当初は何年もほぼ同じでしたが、過去10年間で、この短い期間内で開始以来劇的に変化しました。

C ++は、その汎用性、パワー、豊富な機能セット、そして自分自身を撃つことができるため、完全に習得するのが最も難しい言語の1つであるため、このすべてに言及します!また、すべての注意事項がありますが、それはこのタイプの開発の標準としてトップクラスの業界で使用されている最も強力で優先される言語の1つです。正しく実行されると、高速、簡潔、信頼性が高く、最小のフットプリント。

それ以来、3Dグラフィックスプログラミングとゲームエンジンデザインの学習に重点を置いて、C / C ++で長年独学で学びました。私は、その知識を読み、学習し、有用な実用的な製品とアプリケーションの設計に適用するために、数百から数千時間の検索、研究、その他多くを費やしました。私は自分のスキルセットとクラフトを改善するためにもっと学びたいという意志と希望を常に持っていました。


これが最初の段階でした。その後、最初にDirectX 9.cを読み、作業を開始しました。これは、C / C ++およびC#でも行いました。次に、DirectX 10とLegacy OpenGL 1.0に移行しました。DirectX 11とOpenGL 3.x-4.xが登場し、今ではVulkanで手を試しました。

私は、テキスト形式とビデオ形式の両方のさまざまなオンラインチュートリアルを使用して、成功するゲームエンジンを構築しました。私はすでに数学の強いバックグラウンドを持っていると述べましたが、それは微積分IとIIに限定されていました。私は大学で私の微積分ベースの物理学のクラスからいくつかの知識を持っていたベクトル計算を自分自身に教えなければなりませんでしたが、アフィン変換と解析幾何を持つ線形代数に関しては、特定の方程式、関数、方法、アルゴリズム、コンセプトが必要でした。それから、それらを効率的で読みやすく、信頼性が高く、再利用可能なコードに変換する方法を学ばなければなりませんでした。

これは、メモリ管理、参照カウント、インスタンス化、再帰など、ゲームエンジンのすべてではないにしても多くのコンポーネントで使用されるトピックやアルゴリズムを学ぶ素晴らしい旅でした。ここにすべてをリストできますが、それは3または4の回答スペースを記入するのに十分な情報です。ただし、サブトピックではなく、一般的なトピックのリストを含めます。

さまざまなレンダリングテクニック、レンダリングとシェーダーパイプラインの設定、シェーダーによるシェーディングとライティングテクニック、前処理と後処理、フレームバッファー、バックバッファーを含む、完全に機能するゲームエンジンで構成されるトピックまたはサブジェクトリストを以下に示します。 、画像の読み込み、音声とモデルの読み込みと解析、色の素材プロパティを持つプリミティブシェイプの作成、手動のテクスチャマッピングによるテクスチャと通常の座標、オブジェクト変換、カメラタイプ、シーングラフ階層、テクスチャのマネージャクラス、音声、フォント、およびシェーダとメモリ管理、例外処理を備えたロギングシステム、マルチスレッドおよび並列プログラミング技術、ネットワーキング、物理エンジン、衝突検出、パーティクルジェネレータ、アニメーション、ゲームAI、地形生成、スカイボックスとスカイドーム、ウォーターレンダリング、葉など...、テキストレンダリング用のテクスチャフォント、HUDオーバーレイ、インベントリ、マップおよびマクロ生成、状態システムおよび状態マシンを備えたGUI、および最終的にこれらのオブジェクトの多くを自動化する独自のスクリプト言語を作成するパーサーの作成データファイルを読み込んで、アプリケーションの起動時にそれぞれのコンテナ内のデータオブジェクトと構造を読み込むだけで、再コンパイルすることなく、エンジン内のデータ値を変更できます。最後に、パーサーを作成して独自のスクリプト言語を作成し、これらのオブジェクトの多くを自動化して、それぞれのコンテナー内のデータオブジェクトと構造にデータファイルを読み込むだけで再コンパイルすることなく、エンジン内のデータ値を変更できるようにしますアプリケーションの起動時。最後に、パーサーを作成して独自のスクリプト言語を作成し、これらのオブジェクトの多くを自動化して、それぞれのコンテナー内のデータオブジェクトと構造にデータファイルを読み込むだけで再コンパイルすることなく、エンジン内のデータ値を変更できるようにしますアプリケーションの起動時。


何年もの間、コンパイラー、アセンブラー、および単純なオペレーティングシステムについて学びたいと思っていたアセンブリ言語を学びたいと思っていました。

時間が経ち、私は少し歩み寄り、ハードウェアエミュレーションの学習を始めました。私は特にNESに焦点を合わせましたが、一般的なCPUのハードウェアエミュレーションを学びたいと思いました。これにより、Intelのx86ファミリにある程度精通しているため、コンセプトをすでに知っている命令セットについて学習することになりましたが、6502命令セットを学習する必要がありました。

しかし、これに飛び込むことで、私は結局より多くの研究をすることになり、エンジニアリングの観点から命令セットアーキテクチャについて学び始めました。これにより、CPUが論理ゲートからどのように構築されるか、および論理ゲートが他のさまざまな電気コンポーネントとともにトランジスターからどのように構築されるかについて学習しました。だから私は、トップダウンとボトムアップの2つの視点からこのことを学びました。両方の方法は非常に効果的であり、両方から学ぶことは、ソフトウェアがハードウェアに食い込むブリッジまたはギャップを構築するのに役立つと思います。

これから、ブール代数をリフレッシュしなければならなくなり、K-Map、含意表、ミーリーとムーアの両方のステートマシン、およびバイナリロジックと算術を物理論理ゲートと集積回路に関連付けるさまざまなものについて学習しました。そして、これは私がLogisimで働き始め、HDL、VHDL、Verilogなどを学び始めた過去に私をもたらします...

私は、過去15〜18年間を通してできる限り、暇なときにこれらすべてを学んでいます。


ここに、長年にわたって私を導いてくれたサイトとリンクの一部を示します。これらの多くは、私が最初に学んだサイトの多くがもはや存在しないか、リンクを失って覚えていないか、検索エンジンが検索リストのはるか後ろにそれらを押し込んだため、最近のものです...

  • 言語-C ++

  • 3DグラフィックチュートリアルとリソースWebサイト

  • Youtubeシリーズとチャンネル は、上記のトピックに加えて、ハードウェア、コンピューター、電気工学をカバーしています。リストするのが多すぎるので、ここでそれらのいくつかをリストしますが、最も有用でリソースが豊富です。リンクは提供しませんが、YouTubeでこれらのチャンネルを検索できます。

    • 3Blue1Brown- 高度な数学
    • Bisqwit- 高度なC / C ++プログラミング(アプリケーションプロジェクト)-NESハードウェアエミュレーター
    • Jason Turner- 高度なモダンC ++プログラミング手法
    • javidx9- 高度なC / C ++プログラミング(アプリケーションプロジェクト)-NESハードウェアエミュレーター/一部のアセンブリ
    • MIT OpenCourse-数学とコンピューターサイエンスの大学コース
    • Bilkentオンラインコース -コンピューターサイエンスおよびコンピューターエンジニアリングの大学コース(CPU Design MIPS)
    • Cherno- 高度なC / C ++プログラミングのトピックとアプリケーション-ゲームエンジン開発
    • ベンイーター -ハードウェアエンジニアリング-ブレッドボードによる実用化
    • Neso Academy- ハードウェアエンジニアリング-理論と概念
    • Socratica -Pythonプログラミング
    • Simply Put- ハードウェアエンジニアリング-理論と概念
    • ビット単位 -高度なC / C ++ハードウェアエミュレーションを介したアセンブラーの設計
    • Bo Qian- データ構造とアルゴリズムのC ++トピック。
    • LineByLine -Vulkanプログラミング
    • ジョシュアシャッカー -バルカンプログラミング
    • www.MarekKnows.com -C ++、3D数学およびゲームエンジン開発

そしてこれらは、これらのトピックに関して私が持っているさまざまな本のいくつかを考慮していません。

-注-これは、私自身の個人的な経験の読者へのメッセージに過ぎず、元の質問に答えたり参照したりする試みがないため、投票しないでください。次の数日間は時間があります。参照とリソースのセットとして有用なリンクを提供しながら、OPの質問についての考えを示すためにフォローアップの回答を追加します。ここにいくつかのリンクを含め、このメモを変更するためにこの回答を更新します。遅れており、現在、すでに書いたものを校正して編集する時間はありません。できるときにこれを行います」。


この回答または投稿を更新しました。実際に質問に答える第2部を追加するつもりでしたが、そうするのに十分な評判ポイントがありません。2番目の回答を追加する前に、必要な評価ポイントを構築するのに時間がかかります。この投稿は実際の答えではありませんが、参照として使用し、真の答えの理由についての表を参照します。ソフトウェアとハ​​ードウェア間のギャップを埋めるには、上記のリソースの一部が必要です。
フランシスカグラー

-2

コアでは、CPUは通常、単なるステートマシンです。そのため、論理ゲートとフリップフロップまたはレジスタを組み合わせてステートマシンを作成する方法を理解する必要があります。

ステートマシンは、入力と現在の状態を取得し、それらをブール(および潜在的に算術)ロジックを介して実行し、出力と次の状態を提供します。入力の1つは命令レジスタです。出力の1つは、命令レジスタをリロードするためのソースの選択と選択であり、プログラムカウンタとして機能する別のレジスタをインクリメントまたはロードすることもできます。それに加えて、アドレス可能なメモリを使用すると、命令を順番に実行できます。

命令をシーケンスする方法が得られたら、ロジックを使用してこれらの命令ビットに加えて現在の状態を別の制御ビット群にデコードできます。これらの制御ビットの一部は、算術およびワード全体のロジックを実行できる一連のロジックを制御する入力として機能し、それをALUと呼びます。他のビットは、ALUのデータをロードしたり、入力を選択したりできます。他のビットは、ALUの結果を保存する場所を指定できます。または、アドレス指定レジスタをロードします。または、メモリまたは他の出力に書き込みます。等。

命令セットの設計の一部は、デコード時にすべてのレジスタとステートマシンシーケンスを制御するビットの組み合わせを把握することです。これは何千もの異なる方法で行われ、(再)最適化されていました。

この重要なテーマに関する大学の教科書には少なくとも3つのレベルがあります。


2
これは、MOV操作がどのようにバイナリ値に変換されるかを説明しません。これは、命令MOV操作が値であり、使用するキーワードであることに言及していないため、16〜32ビットのバイナリ値を記憶する必要はありません。
ラムハウンド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.