言語はどのようにしてそれ自体を拡張しますか?[閉まっている]


208

私はC ++を学んでおり、GUIプログラムをコーディングするためのQtの機能のいくつかについて学び始めました。私は自分に次の質問をしました:

以前はOSにウィンドウまたはネットワークを介して通信する方法を要求する構文がなかったC ++(私も完全に理解していないAPIを使用しています)は、C ++自体で作成されたライブラリ介してそのような機能どのようにして突然取得しますか?それはすべて私にはひどく循環しているように見えます。これらのライブラリで考えられるC ++命令はどれですか。

この質問は経験豊富なソフトウェア開発者にとっては些細なことのように思えるかもしれませんが、私は何も直接調査せずに何時間も研究を続けてきました。ライブラリの存在が私には理解できないので、Qtに関するチュートリアルをたどることができなくなりました。


27
std :: coutはどのようにしてモニターに何かを描画しますか?それとも、ハードウェアを理解するコンパイラの上にありますか?
doctorlove 14

14
すばらしい質問です。結局、ハードウェアを勉強するまで答えるのは難しいです。
user541686 2014

17
Qtは言語の拡張ではありません(Qt対応のコンパイラが必要です)。それはあなたの武器に追加される単なるライブラリです。最終的に、最下位レベルでは、すべてのライブラリがシステムコールを介してOSと通信します。システムコールは言語に依存しませんが、OSとCPUアーキテクチャに大きく依存します。
DevSolar 14

8
Afaik、C ++にはインラインアセンブリがあり、ほとんど何でもできる
表示名

9
@DevSolar:実際、Qtは独自の信号スロットメカニズム、リフレクション、およびその他の多くの動的機能を使用して言語を拡張します。そして、それらはC ++コードにコンパイルするためにコンパイラー(メタオブジェクトコンパイラー)を必要とします。
Siyuan Ren 14

回答:


194

コンピュータは玉ねぎのようなもので、純粋なハードウェアの内部コアから最も外側のアプリケーション層まで、多くの層があります。各層はそれ自体の一部を次の外層に公開するため、外層は内層機能の一部を使用できます。

たとえばWindowsの場合、オペレーティングシステムは、Windows上で実行されるアプリケーション用のいわゆるWIN32 APIを公開します。QtライブラリはそのAPIを使用して、Qtを使用するアプリケーションを独自のAPIに提供します。Qtを使用し、QtはWIN32を使用し、WIN32はWindowsオペレーティングシステムの下位レベルを使用します。これがハードウェアの電気信号になるまで続きます。


56
注:LinuxではWIN32 APIではなくLinux APIを呼び出すため、Qtここではその下のレイヤーの抽象化を提供Qtます。
Matthieu M. 14

5
Qtの例についてもう少し詳しく説明すると、C ++の機能を簡単に拡張できるように見えるだけです。現実の場合、彼らは共通のAPIを作成するために、(おそらく)さまざまな「オニオンコア」に多くの労力を費やしました。それらは、移植性のない非標準のバックエンドの上に移植性を提供するものです。
luk32 14

81
コンピューターは玉ねぎのようなものです。それを切ると泣くようになりますが、その後はやや美味しくなります。
alecov 14

3
@ChristopherPfohlええ、コンピューターがチョコレートの箱のようになるのが理解できなかったので、それを使わなければなりませんでした。:)
一部のプログラマは、14

1
@Celeritas先生はおそらく言ったuser32.dll、あるいは多分gdi32.dll
user253751 2014

59

一般的に、ライブラリはまだ不可能ではないことを可能にすることはできません。

ただし、C ++プログラムで使用できるようにするために、ライブラリをC ++で作成する必要はありません。C ++で記述されている場合でも、C ++で記述されていない他のライブラリを内部で使用する場合があります。したがって、C ++がそれを行う方法を提供しなかったという事実は、C ++の外部でそれを行う何らかの方法がある限り、追加が妨げられることはありません。

かなり低いレベルでは、C ++(またはC)によって呼び出される一部の関数はアセンブリで記述され、アセンブリには、C ++で実行できない(または簡単でない)ことを実行するために必要な命令が含まれています。たとえば、システム関数。その時点で、そのシステムコールは、それを止めるものが何もないという理由だけで、コンピューターで可能なすべてのことを実行できます。


他の言語で書かれたライブラリは、すでに他のコンパイラを使用してコンパイルされているということですか?そして、ライブラリによってC ++に提供された各関数呼び出しを、ライブラリのプリコンパイルされたバージョンにリンクする何らかのインターフェイスファイルが必要になるでしょうか。したがって、C ++コンパイラはこれらの呼び出しを何に変換するかを知ることができますか?
Med Larbi Sentissi 2014

2
@MedLarbiSentissi 1)必ずしも他のコンパイラである必要はありません。1つの単一のコンパイラーがアセンブリーを含む複数の言語をコンパイルできる可能性があり(たまたまそうなのですが)、インライン・アセンブリーを使用してC ++をコンパイルできる場合さえあります。2)特定のシステムとコンパイラーによっては、これらの関数をC ++から呼び出せるようにすることは確かにある種のインターフェースファイルで行われるかもしれませんが、その種のインターフェースファイルはすでにC(またはC ++)ヘッダーであり、C ++から直接使用できます。

1
@MedLarbiSentissi:多くのWindowsライブラリは、独自のインターフェイスとコードを含むdllファイルにコンパイルされます。dllをのぞいて、使用できる関数のリストを確認できます。多くの場合、Cヘッダーファイルも付属しています。exeを作成すると、実行に必要なdllのリストが含まれています。OSがexeをロードしようとすると、実行を開始する前にそれらのdllも自動的にロードされます。
Mooing Duck 14

8
この答えは、「魔法」が呼び出される他の言語に完全にあることを示唆しているようですが、実際、最新のオペレーティングシステムを構成するほとんどのコードはCです(非常にハードウェア関連またはパフォーマンス重視のパーツのみがアセンブリで記述されています)。代わりにC ++を使用することは間違いなく可能です。重要なのは、「魔法」はなく、そのような強力な抽象化を構築するために言語が作成され、ハードウェアとやり取りできるようになると、可能性はほとんど無限になるということです。
Matteo Italia

1
@hvdこの議論での全体の矛盾は、あなた(そして他の人)がCをそれに指定された機能として定義していることだと思います。実際、コンパイラーは指定されたものよりもはるかに多くを追加するため、Cが何であるかという質問は答えるのが簡単ではありません。私にとって言語の特別なこと(つまり、それがそうであること)は、プログラムの流れと構造化の可能性を表現するメタウェイです。構造化された要素は重要ではありません。それは、コンパイラーが望みどおりに追加できるASMコードです
LionC

43

CとC ++には、OPが話しているこのすべての拡張性を可能にする2つのプロパティがあります。

  1. CおよびC ++はメモリにアクセスできます
  2. CおよびC ++は、CまたはC ++言語以外の命令のアセンブリコードを呼び出すことができます。

カーネルまたは基本的な非保護モードのプラットフォームでは、シリアルポートやディスクドライブなどの周辺機器は、RAMと同じようにメモリマップにマップされます。メモリは一連のスイッチであり、周辺機器のスイッチ(シリアルポートやディスクドライバーなど)を切り替えると、周辺機器が便利な機能を実行できるようになります。

プロテクトモードのオペレーティングシステムでは、ユーザー空間からカーネルにアクセスする場合(ファイルシステムに書き込む場合や画面にピクセルを描画する場合など)、システムコールを行う必要があります。Cにはシステムコールを作成する命令はありませんが、Cは正しいシステムコールをトリガーできるアセンブラコードを呼び出すことができます。これにより、Cコードがカーネルと通信できるようになります。

特定のプラットフォームのプログラミングを簡単にするために、システムコールは、自分のプログラム内でいくつかの便利な機能を実行できるより複雑な関数にラップされています。1つは(アセンブラを使用して)システムコールを直接呼び出すことは自由ですが、プラットフォームが提供するラッパー関数の1つを使用する方がおそらく簡単です。

システムコールよりもはるかに役立つ別のレベルのAPIがあります。mallocを例にとります。これは、システムを呼び出してメモリの大きなブロックを取得するだけでなく、行われていることを維持しながらすべての本を実行することによってこのメモリを管理します。

Win32 APIは、いくつかのグラフィック機能を共通のプラットフォームウィジェットセットでラップします。Qtは、Win32(またはX Windows)APIをクロスプラットフォームの方法でラップすることにより、これをさらに進めます。

基本的に、CコンパイラーはCコードをマシンコードに変換しますが、コンピューターはマシンコードを使用するように設計されているため、Cがライオンズシェアやコンピューターが実行できることを実行できると期待する必要があります。ラッパーライブラリーが行うことは、あなたのために重い仕事をするだけなので、あなたがする必要はありません。


#2に関する警告:CおよびC ++は、コンパイラーが理解して期待する「呼び出し規約」に準拠する関数のみを実行可能に呼び出すことができます。(アセンブリコードは、好きな規則を使用することも、まったく使用しないこともできます。そのため、コードを直接呼び出すことができない場合があります。)幸い、すべての自尊心コンパイラは、プラットフォームの一般的な規則を使用する組み込みの方法を提供します。(たとえば、Windows Cコンパイラでは、「cdecl」、「stdcall」、または「fastcall」の規則を使用する関数を使用できます。)ただし、アセンブリコードはコンパイラが知っている規則を使用する必要があります。そうしないと、CおよびC ++はt直接呼び出す。
cHao 14

2
また、メモリマップI / Oは一般的ですが、全体ではありません。たとえば、PCは通常、x86の「I / Oポート」というまったく異なるメカニズムを使用して、シリアルポートやディスクドライブなどをアドレス指定します。(ビデオバッファーは通常メモリマップされますが、ビデオモードなどは通常I / Oポートを介して制御されます。)
cHao

@cHao:もちろん、INPとOUTPを使用する従来のアプローチは、DMAを支持して取り残されています。PCI生成は、メモリマップされた特殊機能レジスタでより多くのことを行うようですが、デバイスを重複しない領域に自動的にマップし、ドライバーからそれらを検出する方法があり、I / Oポートではより少ない方法です。
Ben Voigt 2014

最新のペリフェラルはバルクデータ転送にDMAを使用しますが、アドレス可能なメモリを使用してDMAコントローラーをプログラムします
doron

@doron:うーん、少なくとも正気なら、PCのI / Oアドレス空間(メモリ空間ではない)を介してDMAコントローラをプログラムします。最近のx86 CPUは、パフォーマンスを改善するためにメモリアクセスを並べ替えるのが好きです。MMIOを使用すると、それは悲惨な結果になる可能性があります。そのため、これらのアドレスをuncacheabkeにしないように注意し、すべての適切な場所にシリアル化命令配置する必要があります。OTOH、x86自体は、I / Oスペースへの読み取りと書き込みがプログラム順に行われることを保証します。これが、重要なものの多くが依然としてI / O空間(通常、ポインターを介してアクセスできない)を介して行われる理由であり、おそらく常にそうなります。
cHao 14

23

言語(C ++ 11のような)は紙に書かれた仕様で、通常は英語で書かれています。最新のC ++ 11ドラフトを調べてください(または、ISOベンダーから高価な最終仕様を購入してください)。

一般的に、一部の言語を実装したコンピューターを使用します(原則として、コンピューターなしでC ++プログラムを実行できます。たとえば、人間の奴隷の束を使用してそれを解釈します。これは非倫理的で非効率的です)。

C ++実装一般は、一部のオペレーティングシステム上で動作し、それと通信します(一部の実装固有のコードを使用して、多くの場合、一部のシステムライブラリで)。通常、その通信はシステムコールを通じて行われますLinuxカーネルで使用可能なシステムコールのリストについては、たとえばsyscalls(2)を参照してください。

アプリケーションの観点から見ると、syscallはSYSENTERx86-64のような基本的な機械語命令であり、いくつかの規則(ABI)があります。

私のLinuxデスクトップで、Qtライブラリは、上にあるX11の X11サーバとの通信のクライアントライブラリのXorgスルーX、Windowsのプロトコル

Linuxでは、ldd実行可能ファイルでを使用して、ライブラリへの依存関係の(長い)リストを表示します。pmap実行中のプロセスでを使用して、実行時に「ロード」されているプロセスを確認します。ところで、Linuxでは、アプリケーションはおそらくフリーソフトウェアのみを使用しています。ソースコード(QtからXlib、libc、...カーネルまで)を調べて、何が起こっているのかを理解することができます。


2
参考までに、ANSIはC ++ 11仕様を60ドルというやや安価な価格で販売しています。(以前はその半分でしたが、インフレです。:P)INCITS / ISO / IEC 14882と表示されていますが、少なくともISOが提供する基本仕様と同じです。エラータ/ TRについては不明です。
cHao 2014

19

あなたが見逃しているコンセプトはシステムコールだと思います。各オペレーティングシステムは、低レベルのオペレーティングシステム関連のことを実行するために利用できる膨大な量のリソースと機能を提供します。通常のライブラリ関数を呼び出す場合でも、システムコールがバックグラウンドで行われている可能性があります。

システムコールは、オペレーティングシステムの機能を活用する低レベルの方法ですが、複雑で使いにくい場合があるため、APIに「ラップ」されることが多いため、直接処理する必要がありません。しかしその下では、O / S関連のリソースに関係するほとんどすべてのことで、印刷、ネットワーク、ソケットなどのシステムコールが使用されます。

ウィンドウの場合、Microsoft WindowsのGUIは実際にカーネルに書き込まれているため、ウィンドウの作成、グラフィックスの描画などのシステムコールがあります。他のオペレーティングシステムでは、GUIがカーネルの一部ではない場合があります。私が知る限り、GUI関連のシステムコールはなく、低レベルのグラフィックスと入力関連のコールが利用できる場合は、さらに低いレベルでしか作業できません。


3
欠けている重要なことは、それらのシステムコールは決して魔法ではないということです。これらは、通常C(++)で記述されたカーネルによって処理されます。さらに、syscallは必要ありません。メモリ保護のない基本的なOSでは、ピクセルをハードウェアフレームバッファに直接配置することでウィンドウを描画できました。
el.pescado 2014

15

良い質問。すべての新しいCまたはC ++開発者はこれを念頭に置いています。この記事の残りの部分では、標準のx86マシンを想定しています。Microsoft C ++コンパイラを使用している場合は、メモ帳を開いて次のように入力します(ファイル名はTest.c)。

int main(int argc, char **argv)
{
   return 0
}

そして、このファイルを(開発者のコ​​マンドプロンプトを使用して)コンパイルします。cl Test.c /FaTest.asm

次に、メモ帳でTest.asmを開きます。表示されているのは翻訳されたコードです-C / C ++はアセンブラーに翻訳されています。ヒントはわかりますか?

_main   PROC
    push    ebp
    mov ebp, esp
    xor eax, eax
    pop ebp
    ret 0
_main   ENDP

C / C ++プログラムは、メタル上で実行するように設計されています。つまり、下位レベルのハードウェアにアクセスできるため、ハードウェアの機能を簡単に活用できます。たとえば、x86マシンでCライブラリgetch()を作成するとします。

アセンブラーに応じて、次のように入力します。

_getch proc 
   xor AH, AH
   int 16h
   ;AL contains the keycode (AX is already there - so just return)
ret

私はそれをアセンブラーで実行し、.OBJを生成します-getch.objという名前を付けます。

次に、Cプログラムを記述します(#includeは一切行いません)

extern char getch();

void main(int, char **)
{
  getch();
}

次に、このファイルにGetChTest.cという名前を付けます。getch.objを渡してこのファイルをコンパイルします。(または、個別に.objにコンパイルし、GetChTest.Objとgetch.Objをリンクして、GetChTest.exeを生成します)。

GetChTest.exeを実行すると、キーボード入力を待機していることがわかります。

C / C ++プログラミングは言語だけではありません。優れたC / C ++プログラマーになるには、実行するマシンのタイプをよく理解している必要があります。メモリ管理がどのように処理されるか、レジスタがどのように構造化されるかなどを知る必要があります。通常のプログラミングではこれらすべての情報は必要ないかもしれませんが、それらは非常に役立ちます。基本的なハードウェアの知識は別として、コンパイラーがどのように動作するか(つまり、どのように変換されるか)を理解していれば、確かに役立ちます。これにより、必要に応じてコードを微調整できます。おもしろいパッケージです!

どちらの言語も__asmキーワードをサポートしています。つまり、アセンブリ言語コードを混在させることができます。CとC ++を学ぶことで、全体的に丸みのあるプログラマーになるでしょう。

常にアセンブラとリンクする必要はありません。私はそれがあなたがよりよく理解するのに役立つだろうと思ったのでそれを述べました。ほとんどの場合、そのようなライブラリ呼び出しのほとんどは、オペレーティングシステムによって提供されるシステムコール/ APIを利用します(OSはハードウェアの相互作用を行います)。


10

C ++はどのようにしてC ++で記述されたライブラリを介してそのような機能を突然取得しますか?

他のライブラリを使用することに魔法はありません。ライブラリは、呼び出すことができる関数の単純な大きなバッグです。

このような関数を自分で書くことを検討してください

void addExclamation(std::string &str)
{
    str.push_back('!');
}

今、あなたがそのファイルを含めれば、あなたは書くことができます addExclamation(myVeryOwnString);。ここで、「C ++が突然、感嘆符を文字列に追加する機能をどのようにして手に入れたのか」と尋ねるかもしれません。答えは簡単です。それを行うための関数を作成してから、それを呼び出しました。

したがって、C ++がC ++で作成されたライブラリを介してウィンドウを描画する機能を取得する方法に関する質問に答える場合も、答えは同じです。他の誰かがそれを行うための関数を書き、それをコンパイルしてライブラリの形であなたに渡しました。

他の質問は、ウィンドウ描画が実際にどのように機能するかについて回答しますが、ライブラリの機能について混乱しているように思われるので、質問の最も基本的な部分について説明したいと思います。


8

重要なのは、オペレーティングシステムがAPIを公開する可能性と、このAPIの使用方法に関する詳細な説明です。

オペレーティングシステムは、呼び出し規約を備えた一連のAPIを提供します。呼び出し規約は、パラメーターがAPIに与えられる方法、結果が返される方法、および実際の呼び出しを実行する方法を定義しています。

オペレーティングシステムとそれらのコードを作成するコンパイラーはうまく連携して動作するので、通常は考える必要はありません。使用するだけです。


7

ウィンドウを作成するための特別な構文は必要ありません。必要なのは、OSがウィンドウを作成するためのAPIを提供することだけです。このようなAPIは、C ++が構文を提供する単純な関数呼び出しで構成されています。

さらに、CおよびC ++は、いわゆるシステムプログラミング言語であり、任意のポインター(ハードウェアによって一部のデバイスにマップされる可能性がある)にアクセスできます。さらに、アセンブリで定義された関数を呼び出すのもかなり簡単です。これにより、プロセッサが提供するすべての操作が可能になります。したがって、CまたはC ++と少量のアセンブリを使用してOS自体を作成することが可能です。

Qtはいわゆるメタコンパイラーを使用し C ++の構文を拡張するため、Qtは悪い例であることにも言及する必要があります。ただし、これは、OSが提供するAPIを呼び出して実際にウィンドウを描画または作成する機能とは関係ありません。


7

まず、少し誤解されていると思います

以前はOSにウィンドウまたはネットワークを介して通信する方法を要求する構文がなかったC ++はどのように機能しますか

OS操作を実行するための構文はありません。それは意味論の問題です。

C ++自体で作成されたライブラリを介してそのような機能を突然取得する

まあ、オペレーティングシステムは主にCで書かれています。共有ライブラリ(dll)を使用て外部コードを呼び出すことができます。さらに、オペレーティングシステムコードは、システムルーチンをsyscalls *または割り込みを使用して登録できます。これは、アセンブリを使用して呼び出すことができます。多くの場合、その共有ライブラリはそのシステムコールを作成するだけなので、インラインアセンブリを使用する必要はありません。

これに関する素晴らしいチュートリアルは次のとおりです。http//www.win.tue.nl/~aeb/linux/lk/lk-4.html
これ Linux向けですが、原則は同じです。

オペレーティングシステムはグラフィックカード、ネットワークカードなどの操作をどのように行っていますか?これは非常に広いテーマですが、ほとんどの場合、割り込みやポートにアクセスしたり、特別なメモリ領域にデータを書き込んだりする必要があります。これらの操作は保護されているため、いずれにしてもオペレーティングシステムから呼び出す必要があります。


7

他の答えとは少し異なる見方をするために、私はこのように答えます。

(免責事項:私は少し物事を簡略化しています。私が与える状況は純粋に仮説であり、人生に100%忠実であるというよりは概念を実証する手段として書かれています)。

別の観点から考えてみてください。基本的なスレッド化、ウィンドウ処理、およびメモリ管理機能を備えた単純なオペレーティングシステムを作成したとしましょう。C ++ライブラリを実装して、ユーザーがC ++でプログラミングし、ウィンドウの作成、ウィンドウへの描画などを行えるようにする必要があります。問題は、これを行う方法です。

まず、C ++はマシンコードにコンパイルされるため、マシンコードを使用してC ++とインターフェースする方法を定義する必要があります。これが関数の出番であり、関数は引数を受け入れ、戻り値を提供するため、コードの異なるセクション間でデータを転送する標準的な方法を提供します。彼らは、呼び出し規約として知られているものを確立することによってこれを行います

呼び出し規約の状態と、それが実行されますときに関数がそれらを見つけることができるように引数をメモリに配置する必要がありますか。関数が呼び出されると、呼び出し元の関数は引数をメモリに配置し、CPUに他の関数にジャンプするように要求します。他の関数では、呼び出された場所にジャンプする前に、関数が実行することを実行します。つまり、呼び出されるコードは絶対に何でも可能であり、関数の呼び出し方法は変更されません。ただし、この場合、関数の背後にあるコードはオペレーティングシステムに関連し、オペレーティングシステムの内部状態で動作します。

それで、何ヶ月も経って、OSのすべての機能が整理されました。ユーザーは、関数を呼び出してウィンドウを作成し、その上に描画できます。スレッドやあらゆる種類の素晴らしいものを作成できます。ここに問題がありますが、OSの機能はLinuxの機能やWindowsの機能とは異なります。したがって、ユーザーがポータブルコードを記述できるように、ユーザーに標準インターフェイスを提供する必要があると判断しました。ここがQTの出番です。

ご存じのとおり、QTには、オペレーティングシステムが行うようなことを行うための便利なクラスと関数がたくさんありますが、その方法は、基盤となるオペレーティングシステムから独立しているように見えます。これが機能する方法は、QTがユーザーに表示される方法が統一されたクラスと関数を提供することですが、関数の背後にあるコードはオペレーティングシステムごとに異なります。たとえば、QTのQApplication :: closeAllWindows()は、実際には、使用されているバージョンに応じて、各オペレーティングシステムの専用ウィンドウを閉じる関数を呼び出します。Windowsでは、おそらくCloseWindow(hwnd)を呼び出しますが、X Window Systemを使用するOSでは、XDestroyWindow(display、window)を呼び出す可能性があります。

明らかなように、オペレーティングシステムには多くの層があり、そのすべてが多くの種類のインターフェイスを通じて相互作用する必要があります。私が触れたこともない多くの側面がありますが、それらを説明するには非常に長い時間がかかります。オペレーティングシステムの内部動作にさらに興味がある場合は、OS開発wikiをチェックすることをお勧めします

ただし、多くのオペレーティングシステムがC / C ++へのインターフェイスを公開することを選択した理由は、マシンコードにコンパイルするためであり、アセンブリ命令を独自のコードと混在させることができ、プログラマーに大きな自由度を提供します。

繰り返しますが、ここでは多くのことが起こっています。.soや.dllファイルなどのライブラリをC / C ++で記述する必要がなく、アセンブリや他の言語で記述できるようにする方法を説明したいと思いますが、さらに追加すると、記事全体を書いて、それをしたいのと同じくらい、それをホストするサイトがありません。


6

画面に何かを描画しようとすると、コードは他のコードを呼び出し、他のコード(など)を呼び出します。最後に、「システムコール」(CPUが実行できる特別な命令)が存在するようになります。これらの命令は、コンパイラーが「組み込み関数」(コンパイラーがCPUが理解できる特別なコードに変換することによって「特別に」処理する関数)をサポートしている場合、アセンブリーで作成することも、C ++で作成することもできます。彼らの仕事はオペレーティングシステムに何かをするように伝えることです。

システムコールが発生すると、最終的にディスプレイドライバーが画面に何かを描画するように指示されるまで、別の関数(など)を呼び出す関数が呼び出されます。その時点で、ディスプレイドライバーは、実際にメモリではなく、メモリのように書き込むことができるアドレス範囲である物理メモリの特定の領域を調べます。ただし、代わりに、そのアドレス範囲に書き込むと、グラフィックスハードウェアがメモリの書き込みをインターセプトし、画面に何かを描画します。 このメモリ領域への書き込みは、C ++でコーディングできるものです。これは、ソフトウェア側では通常のメモリアクセスにすぎないためです。ハードウェアが異なる方法で処理するだけです。

これは、それがどのように機能するかについての非常に基本的な説明です。


4
Afaikシステムコールは実際にはCPU命令ではなく、組み込み関数とは何の関係もありません。これは、デバイスと通信するオペレーティングシステムカーネルの機能です。
MatthiasB 14

3
@MatthiasB:まあ、あなたは間違っています。なぜならsyscall(そしてそのいとこsysenter)は確かにCPU命令だからです。
user541686 2014

2
これは私自身には明確ではなかったため、回答を改善するためのヒントにすぎませんでした。それを個人的な攻撃などと見なしてはいけません。
MatthiasB 14

1
@MatthiasB:私はそれを個人的に取っているのではありません。私は答えが事実上100%正確ではないことをすでに知っていると言っていますが、それはOPに答えるのに十分な単純化だと思います-したがって、より良い答えを書く方法を実際に知っている場合は、自分で書くか答えるか、時間をかけて私のものを編集してください。価値があると思う追加するものは本当にないので、このページでもっと良いものを見たい場合は、自分で努力する必要があります。
user541686 14

3
システムコールはソフトウェア割り込みを使用して行われます。のような命令sysenterは最適化された呼び出しパスです。これは、割り込みハンドラーによって使用されるコンテキストの切り替えが誰もが望むほど高速ではなかったためです。ISによって実行されるコンテキスト切り替えプロセスの一部は、sysenterプロセッサのモードビットを変更してリング0を設定することです。つまり、すべての特権命令、レジスタ、メモリ、I / O領域へのフルアクセスです。
Ben Voigt 2014

4

C ++プログラムがQtライブラリを使用しています(これもC ++でコーディングされています)。QtライブラリはWindowsのCreateWindowEx関数(kernel32.dll内のCでコーディングされた)を使用します。または、LinuxではXlib(これもCでコーディングされています)を使用している可能性がありますが、Xプロトコルで「私用のウィンドウを作成してください」を意味する生のバイトを送信することもできます

あなたのキャッチ22の質問に関連するのは、「最初のC ++コンパイラはC ++で書かれた」という歴史的なメモですが、実際にはそれはいくつかのC ++概念を備えたCコンパイラであり、最初のバージョンをコンパイルしてそれ自体をコンパイルすることができました。

同様に、GCCコンパイラはGCC拡張機能を使用します。最初にバージョンにコンパイルされ、次にそれ自体を再コンパイルするために使用されます。(GCCビルド手順)


2

質問の見方これは実際にはコンパイラの質問です。

このように見て、アセンブリでコードの一部を記述します(任意の言語で実行できます)。これは、Z ++を呼び出す新しく記述した言語をアセンブリに変換します。簡単にするために、コンパイラ(コンパイラ)と呼びます。 。

これで、このコンパイラーにいくつかの基本的な関数を与え、int、string、配列などを書き込むことができるようになりました。実際には、コンパイラー自体をZ ++で記述できるように十分な機能を与えます。これで、Z ++で書かれたZ ++用のコンパイラーができました。

さらにクールなのは、今持っている機能を使用してそのコンパイラーに機能を追加できるため、以前の機能を使用して新しい機能でZ ++言語を拡張できることです。

たとえば、ピクセルを任意の色で描画するのに十分なコードを記述した場合、Z ++を使用してそれを拡張し、必要なものを描画できます。


0

ハードウェアはこれを可能にするものです。グラフィックメモリは大きな配列(画面上のすべてのピクセルで構成される)と考えることができます。画面に描画するには、C ++またはそのメモリに直接アクセスできる任意の言語を使用して、このメモリに書き込むことができます。そのメモリは、たまたまグラフィックカードからアクセスできるか、グラフィックカード上にあります。

最近のシステムでは、グラフィックスメモリに直接アクセスするには、さまざまな制限があるため、ドライバーを作成する必要があります。ウィンドウ(実際には他の画像と同様の画像)を作成し、その画像をGPUが画面に表示するグラフィックスメモリに書き込むライブラリ。言語に何も追加する必要はありませんが、特定のメモリ位置に書き込む機能はポインタの目的です。


私が言おうとしていたのは、新しいバージョンの言語を書き換える必要があるという意味で、言語自体を「拡張」する必要がないこと、そして興味深いプログラムを実行するために実際には循環的ではないということです。ハードウェアとインターフェースする必要があります。
ジョン14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.