対応できるようにする」という手段に出ます。限定されることになってしまいました。メモリ空間を十全に使うためにどうするか。その回答が「セグメント」の導入です。部分かを示す」ものを追加することで、必要ならば1MBの空間をフルに使いながらも、コードレベルでは64KBのアドレッシングのみで済ませられるようにしたのです。セグメントレジスタです。セグメントレジスタはコード用、データ用、スタック用、汎用の4個(CS,DS,SS,ES)用意され、これにより「コードとデータの分離」も可能となりました。実装されるようになってきます。始まる「プロテクトモード」です。おいてセグメントの定義を変更することでこの仮想化を実現したのです。プロテクトモードにおいてはセグメントレジスタはメモリアドレスを直接表すのではなく、メモリ空間の情報を格納しているセグメントディスクリプタという領域へのポインタとなっています。0x00400000~の1MB」を表していたとして、それが物理的なメモリアドレスのどこに該当するのかは、メモリ管理ユニット(MMU)以外知っている必要がありません。したら物理メモリが割り当てられていない場合もありえます。割当たっていないことを検知して、新しくメモリを割り当てます。データを退避させるなどして)解放して割り当て直します。フラットなメモリ空間を一つのセグメントに割り当てる(=フラットメモリモデル)のが常態化します。ここに至ってセグメントの意味は(コードとデータの分離と保護、及びメモリの仮想化の二つ以外)なくなったといってよいのです。評価が高い回答ほどページの上位に表示されます。remove低評価0回答の評価を下げる下記のような回答は推奨されていません。評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。回答ありがとうございます。C言語をコンパイルし実行するとき、”スタック”というものが使われていると思います。その”スタック”と”スタックセグメント”は同じ・・・だと思っていたのですが違うのでしょうか?(これが勘違いの根端・・・)回答ありがとうございます。使われていると思います。17:29スタックセグメントは、「スタックのある場所」を示すための専用のセグメントだったのです。要するにコードともデータ(静的なデータエリア)とも分離したんですね。レジスタの組み合わせで、実メモリアドレスを決定していました。CSレジスタとIPレジスタの組み合わせで実行しているコードの位置を、DSレジスタと各レジスタないし即値の組み合わせでデータアクセスの実メモリアドレスを決定していました。スタックセグメントは、「スタックのある場所」を示すための専用のセグメントだったのです。要するにコードともデータ(静的なデータエリア)とも分離したんですね。レジスタの組み合わせで、実メモリアドレスを決定していました。CSレジスタとIPレジスタの組み合わせで実行しているコードの位置を、DSレジスタと各レジスタないし即値の組み合わせでデータアクセスの実メモリアドレスを決定していました。17:34ありがとうございます。”スタックセグメント”ではなく”スタック領域”と言い方を区別しているんですね。スタック領域・・・スタックとして使われているメモリ領域を概念的ないい方をしているってことかありがとうございます。”スタックセグメント”ではなく”スタック領域”と言い方を区別しているんですね。8086では前者の互換性のために68KBを1つのセグメントとしてやることで、最大表現である1MBを有効利用した・・・。やることで、最大表現である1MBを有効利用した・・・。コンパイラで「メモリモデル」の指定、ありませんでしたか?)のですが、データ量が多くなれば64KBを超える領域を扱う必要が出てきます。その場合はセグメントレジスタ(この場合DSとES、のちにはFSとGSが追加)の値を変更することで領域をずらしてアクセスするのです。いった形式を取ります。セグメントレジスタはあくまでも「今アクセスする領域」を示しているだけなので、プログラムがどれだけの領域を使っていてもいいのです。適時セグメントレジスタの内容を切り替えれば。コンパイラで「メモリモデル」の指定、ありませんでしたか?)のですが、データ量が多くなれば64KBを超える領域を扱う必要が出てきます。その場合はセグメントレジスタ(この場合DSとES、のちにはFSとGSが追加)の値を変更することで領域をずらしてアクセスするのです。いった形式を取ります。セグメントレジスタはあくまでも「今アクセスする領域」を示しているだけなので、プログラムがどれだけの領域を使っていてもいいのです。適時セグメントレジスタの内容を切り替えれば。増えた「プロテクトモード」において、セグメントの定義が変わったんです。従来(リアルモード)のセグメントは実メモリアドレスのオフセット(20ビット中の上位16ビット)を示していたのに対し、プロテクトモードではより柔軟に、メモリブロックを表すようになっています(このときメモリアドレスも16MB(24ビット)になっています)リアルモードは直接アドレッシング、プロテクトモードはセグメントディスクリプタを介した間接アドレッシング、といえます。増えた「プロテクトモード」において、セグメントの定義が変わったんです。リアルモードは直接アドレッシング、プロテクトモードはセグメントディスクリプタを介した間接アドレッシング、といえます。この質問は収束するのでしょうか。湧き上がる好奇心を否定することはできないですけど、kazuyakazuyaさんの知識は、今はまだ多くのことが「点」で終わっているのです。多くの回答者さんが答えている様々なことが、結び付かないでいる。それは「シェルコード」というただでさえ特殊なプログラミングをしたいと言うところに、断片的な解決策を見出そうと質問をされていることに表れています。それで、データセグメントやスタックセグメントに分割したら、それらの一部ずつをプロセスが使うってことですか?違います。それは今のマルチタスクOSで考える発想が混ざっているのだと思います。16ビットの8086CPUを使う初期のMS-DOSなどのOSは、一部の常駐プログラムを除いて、シングルタスクで動いています。自プログラム以外に同時に複数のプロセスが動いている、と言う発想、と言うか前提がありません。アプリケーションのデータ領域が64KBで足りない場合は、自らがセグメントレジスタを操作して、64KBを超える領域にアクセスする必要があります。OSの管理する領域にアクセスすることもできるし、バグがあれば簡単に破壊できます。データセグメントやスタックセグメントを最初にその実行プログラムに割り当てるのはOSのローダーですが、割り当てられたが最後、その値に責任を持つのは、そのプログラム自身です。CS,DS,SSなどのセグメントレジスタはアドレッシングの際にどれが使われるかと言う点でCPUと言うハードウェアに依存していますが、どこにアクセスしているかは特に16ビット、あるいは32ビット80x86のリアルモードでは、OSからロードされたプログラム(≒プログラマー)自身が用途を把握して、責任を持ちます。この質問は収束するのでしょうか。湧き上がる好奇心を否定することはできないですけど、kazuyakazuyaさんの知識は、今はまだ多くのことが「点」で終わっているのです。多くの回答者さんが答えている様々なことが、結び付かないでいる。それは「シェルコード」というただでさえ特殊なプログラミングをしたいと言うところに、断片的な解決策を見出そうと質問をされていることに表れています。それは今のマルチタスクOSで考える発想が混ざっているのだと思います。16ビットの8086CPUを使う初期のMS-DOSなどのOSは、一部の常駐プログラムを除いて、シングルタスクで動いています。自プログラム以外に同時に複数のプロセスが動いている、と言う発想、と言うか前提がありません。アプリケーションのデータ領域が64KBで足りない場合は、自らがセグメントレジスタを操作して、64KBを超える領域にアクセスする必要があります。OSの管理する領域にアクセスすることもできるし、バグがあれば簡単に破壊できます。データセグメントやスタックセグメントを最初にその実行プログラムに割り当てるのはOSのローダーですが、割り当てられたが最後、その値に責任を持つのは、そのプログラム自身です。CS,DS,SSなどのセグメントレジスタはアドレッシングの際にどれが使われるかと言う点でCPUと言うハードウェアに依存していますが、どこにアクセスしているかは特に16ビット、あるいは32ビット80x86のリアルモードでは、OSからロードされたプログラム(≒プログラマー)自身が用途を把握して、責任を持ちます。12:00ああ、何を勘違いしているのか分かりました。各プロセスが、必要な容量と用途のセグメントを定義して使っているのです。複数のプロセスで同じセグメントを共有することは(基本的には)ありません。ように複数のプロセスでコードセグメントを共有することはありますが、特殊事例ですあるプロセスの「1番目のデータセグメント」と、別のプロセスの「1番目のデータセグメント」は、全く別のものなのです。タスクスイッチと同時にセグメントディスクリプタの内容をごっそり入れ替えることで処理しています。各プロセスは、割り当てたセグメントの中については、他を気にせず自由に使用して良いのです。ああ、何を勘違いしているのか分かりました。各プロセスが、必要な容量と用途のセグメントを定義して使っているのです。複数のプロセスで同じセグメントを共有することは(基本的には)ありません。あるプロセスの「1番目のデータセグメント」と、別のプロセスの「1番目のデータセグメント」は、全く別のものなのです。タスクスイッチと同時にセグメントディスクリプタの内容をごっそり入れ替えることで処理しています。各プロセスは、割り当てたセグメントの中については、他を気にせず自由に使用して良いのです。編集ありがとうございます。いうことか・・・プロセスが”メモリセグメント方式”においてセグメントを決めるんですね。(ほかでも同じだろうけど)dodox86さんの言う通りマルチタスクと仮想記憶の概念が入り混じっていました。メモリセグメントであろうとなかろうとプロセスがスタック・コード領域をどこのアドレスから使い始めるのを決めるという点は同じですよね?(まだ誤解がある気がするのですがセグメントレジスターが登場する以前でもスタック領域の長さ・開始地点はプロセスが勝手に決めれたんでしょうか?)ありがとうございます。プロセスが”メモリセグメント方式”においてセグメントを決めるんですね。マルチタスクと仮想記憶の概念が入り混じっていました。13:058086以前では、実メモリアドレスをそのまま使っていましたし、自分以外のプロセスのことを考慮する必要はないので、スタックの開始地点については「あるがまま」に使用しています。動作に支障を来す可能性もある)8086以前では、実メモリアドレスをそのまま使っていましたし、自分以外のプロセスのことを考慮する必要はないので、スタックの開始地点については「あるがまま」に使用しています。13:32ありがとうございます。腑に落ちない点が1つあるのでお願いします。・64KB固定では本来使える分を使えずもったいないのでセグメントレジスターによってアプリケーション(プロセス)自体がセグメント長と開始地点を制御できるようになった(しなければいけなくなった)ようですが1つのセグメントにつき64KBですよね?すべてのセグメントの合計が64KBではないと8bitCPUとの互換性はとれないんじゃないかと思ったのですがそれは問題ないのですか?ありがとうございます。腑に落ちない点が1つあるのでお願いします。14:40リアルモードの場合は各セグメントは64KB固定です(セグメントレジスタは実メモリアドレス上位16ビットを指定するだけで、その中のオフセットは従来通りのアドレスとして64KB利用できる)。互換なんてものは考慮する必要がないので、杞憂に過ぎません。リアルモードにおいて全てのセグメントレジスタの値を同一にすると、64KBの領域に全てを詰め込むことになり、8bit互換となります。コンパイラなどでは「small」メモリモデルと呼んでいます。リアルモードの場合は各セグメントは64KB固定です(セグメントレジスタは実メモリアドレス上位16ビットを指定するだけで、その中のオフセットは従来通りのアドレスとして64KB利用できる)。互換なんてものは考慮する必要がないので、杞憂に過ぎません。リアルモードにおいて全てのセグメントレジスタの値を同一にすると、64KBの領域に全てを詰め込むことになり、8bit互換となります。コンパイラなどでは「small」メモリモデルと呼んでいます。17:48ありがとうございます。ありがとうございます。18:23https://ja.wikipedia.org/wiki/Intel_808664KBで足りなくなってくると、アプリケーションプログラマーがセグメントレジスタを直々に操作して長さを調節した・・・と書かれています。セグメントレジスタを直々に操作して長さを調節した・・・と書かれています。超えるメモリアクセスも可能です。互換の(64KBで完結している)メモリモデル以外を選択した時点で、アセンブリレベルの互換性はなくなりますが、それは機能強化している以上当たり前のことですね。超えるメモリアクセスも可能です。互換の(64KBで完結している)メモリモデル以外を選択した時点で、アセンブリレベルの互換性はなくなりますが、それは機能強化している以上当たり前のことですね。09:54ありがとうございます。ここで気になっているのですがここのwikiで書かれている>64KB以上のメモリ空間にアクセスする手法が用いられるようになったは、セグメントレジスターとオフセットを組み合わせて20bitを使うようになった、メモリセグメントのことを指しているんでしょうか?ありがとうございます。10:38その通りです。アセンブリのレベルで、アドレッシング時にセグメントレジスタの内容を常に意識する必要が出てくるため、煩雑になったのです。アセンブリのレベルで、アドレッシング時にセグメントレジスタの内容を常に意識する必要が出てくるため、煩雑になったのです。回答にも書いてますが、セグメントディスクリプタの情報として、「実メモリにある」状態かどうかは分かる(Presentビット)ので、そのときにスワップイン・スワップアウトをやるだけのことです。実際にはセグメントディスクリプタをセグメントレジスタにロードした時点でPresentビットが立っていないとセグメント不在例外が発生し、例外ハンドラ内でメモリのスワップインや割り当てが行われます。回答にも書いてますが、セグメントディスクリプタの情報として、「実メモリにある」状態かどうかは分かる(Presentビット)ので、そのときにスワップイン・スワップアウトをやるだけのことです。実際にはセグメントディスクリプタをセグメントレジスタにロードした時点でPresentビットが立っていないとセグメント不在例外が発生し、例外ハンドラ内でメモリのスワップインや割り当てが行われます。11:50一応確認したいのですがHDDに退避させることがスワップアウトですよね?ページングを無効にした80386では物理アドレス空間に複数のタスクの空間を共存させているがHDDに退避させることができず物理アドレス空間が足りなくなったらエラーになる。・・・と言われていたのですが確認してみたところ確かにPがありました。物理アドレス空間が足りなくなったらエラーになる。確認してみたところ確かにPがありました。なんでもないですすみません。13:01確かに80286では物理アドレスになるんですが、プロテクトモードでは仮想記憶1GBまでが利用可能です。考えた場合、あるタスクにとってのアドレスAと、別のタスクのアドレスAは(同じ物理アドレスですが)別のものである必要があります(共有しているメモリ領域でない限り)。これを実現するためにPresentビットを使用したスワップイン/アウトが利用されています。確かに80286では物理アドレスになるんですが、プロテクトモードでは仮想記憶1GBまでが利用可能です。考えた場合、あるタスクにとってのアドレスAと、別のタスクのアドレスAは(同じ物理アドレスですが)別のものである必要があります(共有しているメモリ領域でない限り)。これを実現するためにPresentビットを使用したスワップイン/アウトが利用されています。セグメントを割り振るような設計になるってことですか?キャンセル完了するlink+4こんにちは。その「メモリセグメント」は、MMU(メモリ管理ユニット=仮想メモリを実現するためのハードウェア)と言うにはあまりに稚拙過ぎるハードウェアです。8086という30年以上前のCPUで16ビットのアドレス・レジスタで無理っと20ビットのメモリ空間をアクセスできるようにするために工夫された仕組みです。因みにその図は「メモリ全体を示している」がほぼ正解です。その「メモリセグメント」とMMUのセグメント方式やページング方式をごっちゃにすると理解できる筈がありません。30年以上前の技術である「メモリセグメント」を今は使うことはまずありませんので、特殊なケースを除き忘れて良いと思いますよ。セグメント方式のMMUは正直複雑怪奇で理解するのは超苦労する上に実際に使われる場面はあまりないので、ページング方式のMMUを理解すると良いと思います。ページング方式は比較的単純なので理解しやすいです。(と言っても結構難易度高いですが。評価が高い回答ほどページの上位に表示されます。remove低評価0回答の評価を下げる下記のような回答は推奨されていません。評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。回答ありがとうございます。なにが違うんですか?回答ありがとうございます。物理アドレスを直接セグメント(スタックとかの)に区切って直接つかうようなことを書いていますが”セグメント方式”は、物理アドレスをスタックセグメントとか関係なく区切っていって、これを与えられたプロセスがスタックとかのセグメント領域を決めるのだと思いましたが・・・。スタックとかのセグメント領域を決めるのだと思いましたが・・・。12:28(まず、無駄な空行を開けるのはやめましょう。総称という意味その通りです。同じ意味で使っていますか?回答にも記載したように「メモリセグメント」と「セグメント方式」は別物です。前者は30年前以上の技術でアドレス空間を広げる単純な工夫です。後者はMMUの方式の1つです。前者はメモリ保護を提供しません。後者はメモリ空間をプロセスごとに分離し、プロセス間のメモリ保護を提供できます。見る限り事実上「同じもの」ですね。(まず、無駄な空行を開けるのはやめましょう。