セグメントレジスタの値を変更できないのはなぜですか?(マズム)
質問
私はアセンブリ言語を独学することにしました。
セグメント レジスタの値を変更しようとすると、プログラムがコンパイルされないことがわかりました。
私が見つけたすべての記事には、実際に少なくとも 4 つのセグメント レジスタの値を変更できると記載されていますが、何が得られるでしょうか?
私が実際に興味があるのは、現時点ではその理由だけであり、これらのアドレスを変更する本当の目的はありません。
解決
その理由に興味があるとおっしゃっていましたので、次のように答えます。
リアル モードでは、セグメントは物理メモリへの 64K の「ウィンドウ」であり、これらのウィンドウは 16 バイトの間隔で配置されます。プロテクト モードでは、セグメントは物理メモリまたは仮想メモリへのウィンドウであり、そのサイズと位置は OS によって決定されます。セグメントには、プロセスがアクセスするために必要な特権レベルなど、他の多くのプロパティがあります。
これ以降、私が言うことはすべて保護モードについて言及します。
メモリ内にはグローバル記述子テーブル (GDT) と呼ばれるテーブルがあり、これらのウィンドウのサイズや位置、その他のプロパティに関する情報が保存されます。プロセスごとにローカル記述子テーブルが存在する場合もありますが、それらは同様に機能するため、ここでは GDT にのみ焦点を当てます。
セグメント レジスタにロードする値は、 セグメントセレクター. 。これは、GDT または LDT へのインデックスであり、追加のセキュリティ情報が少し含まれています。当然のことながら、プログラムが GDT の範囲外にある記述子をロードしようとすると、例外が発生します。また、プロセスがセグメントにアクセスするための十分な特権を持たない場合、または他の何かが無効な場合は、例外が発生します。
例外が発生すると、カーネルがそれを処理します。この種の例外は、おそらくセグメンテーション違反として分類されるでしょう。したがって、OS はプログラムを強制終了します。
最後に注意点が 1 つあります。x86 命令セットでは、セグメント レジスタに即値をロードできません。中間レジスタ、メモリ オペランド、またはセグメント レジスタへの POP を使用する必要があります。
MOV DS, 160 ;INVALID - won't assemble MOV AX, 160 ;VALID - assembles, but will probably result in an MOV DS, AX ;exception, and thus the death of your program
このアーキテクチャでは大量のセグメントが可能であることを指摘しておく必要があると思います。しかし、私の知る限り、主流の x86 オペレーティング システムに関しては、セグメント レジスタはいくつかの目的しか果たしません。
- ユーザー空間のプロセスが相互に、または OS に害を及ぼさないようにするなどのセキュリティ メカニズム
- マルチ/マルチコアプロセッサの扱い
- スレッドローカルストレージ:最適化として、一部のオペレーティング システム (Linux および Windows を含む) では、スレッド ローカル ストレージ (TLS) にセグメント レジスタを使用します。スレッドは同じアドレス空間を共有するため、システム コールを使用したりレジスタを無駄にしたりせずに、スレッドが TLS 領域の場所を「知る」のは困難です。ただし、セグメント レジスタは実際には役に立たないため、高速 TLS のためにセグメント レジスタを「無駄」にしても問題はありません。これを設定するとき、OS はセグメント レジスタをスキップして、セグメント レジスタへの参照によってトリガーされる GDT/LDT ルックアップをキャッシュするために使用される「隠し」レジスタである記述子キャッシュ レジスタに直接書き込む可能性があることに注意してください。セグメントレジスタから読み取る場合は表示されません。
TLS のスレッドごとのセグメントを除けば、実際には少数のセグメント (プロセッサ数の倍) のみが使用され、OS によってのみ使用されます。アプリケーションプログラムは、 完全に セグメントレジスタを無視します。
これは OS の設計によるものであり、技術的な制限によるものではありません。セグメント レジスタを操作するためにユーザー空間プログラムを必要とする組み込みオペレーティング システムがある可能性がありますが、私は知りません。
他のヒント
Windows 実行可能ファイルを作成していますか?
プロテクト モード (Win32) では、セグメント レジスタは使用されなくなりました。
参照:
メモリモデルは、16ビットの世界の昔とも劇的に異なります。Win32では、メモリモデルやセグメントに関心を持つ必要はもうありません。メモリモデルは1つだけです。フラットメモリーモデル。64K セグメントはもうありません。メモリは、4 GBの大きな連続空間です。それはまた、セグメントレジスタで遊ぶ必要がないことを意味します。任意のセグメントレジスタを使用して、メモリスペースの任意のポイントに対処できます。これはプログラマーにとって大きな助けになります。これがWin32アセンブリプログラミングをCと同じくらい簡単にする理由です