

これを読んでいると、以下の文がありました。

<https://ja.wikipedia.org/wiki/Intel_8086>

>
> 演算用のアドレスレジスタのほかに、セグメントレジスタという、アドレス変換のための16ビットのレジスタを持っていることである。実際にCPUがアクセスするアドレスは、16ビット幅のレジスタによって指定された64KBのアドレスに、さらに16ビット幅のセグメントレジスタの値を16倍（左に4ビットシフト）して加算したアドレスとするため、1MBのメモリ空間を利用できた。

これは、

セグメントレジスタ：0x0000  
アドレスレジスタ：0x00ff  
と、  
セグメントレジスタ：0x000f  
アドレスレジスタ：0x000f

は同じ場所を示すということでしょうか。  
そうだとして、なんのためにそのような仕様にしたのでしょうか。  
メモリ空間を64KBから1MBに増やすことが目的なら、セグメントレジスタの幅を4bitにすればいいのではないのでしょうか。そうすれば、セグメントレジスタ＋アドレスレジスタで20bit、つまり1MBを表現できるわけですし。


CC BY-SA 4.0
2020-01-04T01:35:00.190
61953
2020-01-09T02:12:56.417
2020-01-06T00:26:48.707
3060
37013
question
c operating-system
8086のセグメントレジスタはなぜ16bitの幅を持っているのですか？


８０８６は１６ビットCPUなので、レジスタはみんな１６ビットです  
で、セグメントレジスタは１６ビット必要だからその幅、ということになります。  
１Mを表現するだけ、なら４ビットあれば事は足りますが、それだけではないってことですねー


CC BY-SA 4.0
2020-01-04T03:03:24.510
61956
2020-01-04T03:03:24.510
27481
61953
answer


「なぜ」の回答は @y_waiwai さんの通り 16bit CPU だから。わざわざ 4bit レジスタなんてものを用意すると `PUSH` /
`POP` 等で困ってしまいます。

もう一つ理由を挙げるなら物理アドレスの表記方法が複数あるほうがソフトウエアの実装に便利だから。

物理アドレス [0x1EEE8, 0x2345F] の範囲のデータを、物理アドレス 0x4FF08 からにコピーしたいという場合

  * セグメントレジスタが 4bit の場合  
セグメントレジスタの値を、コピー元で１回、コピー先で１回、違うタイミングで変更する必要がある。セグメントレジスタを更新するとオフセットは計算しなおし。

  * セグメントレジスタが 16bit の場合  
コピー元として [0x1EEE:0x0008-0x1EEE:0x457F] コピー先を [0x4FF0:0x0008-]
に正規化してから開始すると途中でセグメントレジスタを更新しなくてよい。オフセットだけで処理可能

処理開始時に正規化すると１オブジェクトの処理中にセグメントレジスタを更新しなくてよいというのはソフトウエア実装側としては楽できます（＝高速）。逆に言うと
8086 では１オブジェクトの大きさがメモリ上 64KiB を超過すると、処理中に必ずセグメントレジスタの更新が必要で超絶遅くなります。

セグメントレジスタが 4bit なマイコンとしては Renesas RL シリーズなんかがそうですね。 8086 ユーザーを取り込むべくレジスタ名として
`CS` / `ES` なんて名前が付けてありますが実装は全く異なるです。小規模用途向けマイコンだから 64KiB
を超えるようなデータを扱うことはまれという設計思想でそうなっています。


CC BY-SA 4.0
2020-01-04T07:26:01.007
61961
2020-01-04T07:26:01.007
8589
61953
answer


Wikipediaの資料を見たなら、引用されている文の直後の文も良く読んでみると良いでしょう。  
簡単に言えば、貴方が疑問に思った点と、設計者が重視した点が違うから、と言うことでしょう。  
以下で太字にしたのは私(引用者)ですが、その部分が重要だと思われます。

日本語のページでは以下の記述が続いています。

> 8086のアーキテクチャでは、プログラム内で通常表現されるアドレスの値は16ビット幅で64KBのメモリ空間である。
> **当時、64KBのメモリ空間は1つのプログラムにとっては十分に広大であり[3]、セグメント機構はマルチタスクのために用意された。(8086には保護がないので、アプリケーションがセグメントレジスタを操作できるが、本来はOSが操作するものである。)**
> 内蔵する4本のセグメントレジスタの値を全て同一にすると、8ビットの8080と同等の環境となり、
> **8080用ソースを8086へ移植するのが容易であるほか、実行バイナリのリロケータブル化が容易であるといったメリットもあった。**
>
> 後に批判の的となってしまったセグメント方式だが、互換性を重視しつつ開発が短期間で完了でき、かつコストパフォーマンスに優れた選択肢であった。
> **これは、当時モトローラと激しいシェア争いを演じていたintelにとって極めて重大な要素だった。**  
>
> メモリ空間を1MBとしたのは、当時使われていた40DIPパッケージにアドレス・データバスを割り当てる際に、アドレスピンを効率良く増やして割り当てられる値であったとも言われる。

更には英語版のページもGoogleで簡単に翻訳出来るので、見てみるとより詳しい内容が記述されています。いくつか該当するだろう記述を抜粋します。

[Intel 8086 - Wikipedia](https://en.wikipedia.org/wiki/Intel_8086)

> 多くのプログラマーによって複雑で扱いにくいと考えられていますが、このスキームには利点もあります。 **小さなプログラム（64
> KB未満）を独自のセグメントの固定オフセット（0000など）からロードして、再配置の必要性を回避し、最大15バイトのアライメントの無駄を省くことができます。**
>
> Morseらによると、[9]設計者は、16
> MBの物理アドレス空間を作成するために、実際には（4ビットではなく）8ビットシフトを使用することを考えました。
> **ただし、これによりセグメントが256バイト境界で開始され、1976年頃には1
> MBがマイクロプロセッサーにとって非常に大きいと見なされたため、この考えは却下されました。また、追加の4つのアドレスバスピンに対して、低コストの40ピンパッケージで使用可能なピンが十分ではありませんでした。**
>
>
> 簡単に言えば、これはトレードオフです。メモリが16ビット単位でのみアクセスされるようにメモリアドレス指定が簡素化されると、メモリの使用効率が低下します。Intelはロジックをより複雑にすることを決定しましたが、メモリの使用はより効率的です。
> **これは、ユーザーが今日使用しているメモリサイズよりもメモリサイズが大幅に小さく、かつ貴重であった時代でした。** [10]：5–26
>
> 古いソフトウェアの移植  
>
> **小さなプログラムでは、セグメンテーションを無視して、単純な16ビットアドレス指定を使用できます。これにより、8ビットソフトウェアを8086に非常に簡単に移植できます。**
> ほとんどのDOS実装の作成者は、CP/Mに非常によく似たアプリケーションプログラミングインターフェイスを提供するだけでなく、シンプルな.com実行可能ファイル形式CP/Mへ。
> **8086とMS-
> DOSが新しい場合、これは重要でした。なぜなら、多くの既存のCP/M（およびその他の）アプリケーションを迅速に利用可能にし、新しいプラットフォームの受け入れを大幅に容易にするためです。**

他に以下のページもありますが、上記の繰り返しに近いのでリンクだけ紹介。  
[x86 memory segmentation -
Wikipedia](https://en.wikipedia.org/wiki/X86_memory_segmentation)

ちなみに日本語Wikipediaの脚注に以下の記述があります。標準で1MB(実際は640KB程度)の範囲を安価に用意出来るようになるまでには結構時間がかかったと思います。

> **参考までに、初代IBM PCはRAM 64KB(16KBモデルもあったが売れず)、初代NEC PC-9801はRAM 128KBだった。**

本当に詳しくは、英語版Wikipediaの下の方にリンクのあるIEEE論文誌の記事をワード文書にした以下を見れば書いてあるかもしれません。  
読んでいないので何がどうとかは言えませんが。  
[Intel Microprocessors : 8008 to 8086 by Stephen P. Morse et
al.](http://stevemorse.org/8086history/8086history.doc)  
**追記：**  
上記IEEE論文誌記事を読むと、「何故セグメントレジスタが16bitだったか」というそのものズバリは書いて無いようですが、@y_waiwaiさん
@774RRさんが書いたように16bitではないレジスタは検討の土台にも登っていなかったように思われますね。  
そしてセグメント境界は、256バイトでさえメモリの分断化が懸念されて採用されなかった訳です。64KB境界は言わずもがな。  
以下に関連しそうな記述を抜粋します。同じく太字は引用者によるものです。

> VII. Objectives and Constraints of 8086
>
> The goals of the 8086 architectural design were to provide symmetric
> extensions of existing 8080 features, and to add processing capabilities not
> found in the 8080.  
>  These features included 16-bit arithmetic, signed 8- and 16-bit arithmetic
> (including multiply and divide), efficient interruptible byte-string
> operations, improved bit-manipulation facilities, and mechanisms to provide
> for re-entrant code, position-independent code, and dynamically relocatable
> programs.  
>  By now memory had become very inexpensive and microprocessors were being
> used in applications that required large amounts of code and/or data.  
>  Thus another design goal was to be able to address directly more than 64k
> bytes and support multiprocessor configurations.
>
> 8086アーキテクチャ設計の目標は、既存の8080機能の対称的な拡張機能を提供し、8080にはない処理機能を追加することでした。  
>
> これらの機能には、16ビット演算、符号付き8および16ビット算術（乗算および除算を含む）、効率的な割り込み可能なバイト文字列操作、改良されたビット操作機能、再入可能なコードを提供するメカニズム、位置に依存しないコード、動的に再配置可能なプログラム、が含まれています。  
>  今ではメモリが非常に安価になり、大量のコードやデータを必要とするアプリケーションでマイクロプロセッサが使用されていました。  
>  したがって、別の設計目標は、 **64kバイト以上を直接アドレス指定し** 、マルチプロセッサ構成をサポートできるようにすることでした。
>
> VIII. The 8086 Instruction-Set Processor  
>  A. Memory Structure  
>  1\. Memory Space.
>
> Since the 8086 processor performs 16-bit arithmetic, the address objects it
> manipulates are 16 bits in length.  
>  Since a 16-bit quantity can address only 64K bytes, additional mechanisms
> are required to build addresses in a megabyte memory space.  
>  The 8086 memory may be conceived of as an arbitrary number of segments,
> each at most 64K bytes in size.  
>  Each segment begins at an address which is evenly divisible by 16 (i.e.,
> the low-order 4 bits of a segment's address are zero).  
>  At any given moment the contents of four of these segments are immediately
> addressable.  
>  These four segments, called the current code segment, the current data
> segment, the current stack segment, and the current extra segment, need not
> be unique and may overlap.  
>  The high-order 16 bits of the address of each current segment are held in a
> dedicated 16-bit segment register.  
>  In the degenerate case where all four segments start at the same address,
> namely address 0, we have an 8080 memory structure.
>
> **8086プロセッサは16ビット演算を実行するため、それが操作するアドレスオブジェクトの長さは16ビットです。**  
>  16ビットの量は64Kバイトしかアドレスできないため、メガバイトのメモリ空間にアドレスを構築するには追加のメカニズムが必要です。  
>  8086メモリは、それぞれ最大64Kバイトのサイズの任意の数のセグメントとして考えられます。  
>  各セグメントは、16で割り切れるアドレスで始まります（つまり、セグメントのアドレスの下位4ビットはゼロです）。  
>  いつでも、これらのセグメントの4つの内容はすぐにアドレス指定可能です。  
>  これらの4つのセグメントは、現在のコードセグメント、現在のデータセグメント、現在のスタックセグメント、および現在の追加セグメントと呼ばれ、
> **一意である必要はなく、重複してもかまいません。  
>  各現在のセグメントのアドレスの上位16ビットは、専用の16ビットセグメントレジスタに保持されます。**  
>  4つのセグメントすべてが同じアドレス、つまりアドレス0で始まる縮退したケースでは、8080メモリ構造になります。
>
> Various alternatives for extending the 8080 address space were considered.  
>  One such alternative consisted of appending 8 rather than 4 low-order zero
> bits to the contents of a segment register, thereby providing a 24-bit
> physical address capable of addressing up to 16 megabytes of memory.  
>  This was rejected for the following reasons:
>
>   * Segments would be forced to start on 256-byte boundaries, resulting in
> excessive memory fragmentation.
>   * The 4 additional pins that would he required on the chip were not
> available.
>   * It was felt that a 1-megabyte address space was sufficient.
>

>
> 8080アドレス空間を拡張するためのさまざまな選択肢が検討されました。  
>
> そのような代替案の1つは、セグメントレジスタの内容に下位4ビットではなく8ビットを追加することで、最大16メガバイトのメモリをアドレス指定できる24ビットの物理アドレスを提供します。  
>  これは、次の理由で拒否されました。
>
>   * **セグメントは256バイトの境界で強制的に開始されるため、メモリが過度に断片化されます。**
>   * 彼がチップ上で必要とする4つの追加ピンは利用できませんでした。
>   * 1メガバイトのアドレス空間で十分であると感じられました。
>

>
> B. Register Structure  
>  The 8086 processor contains three files of four 16-bit registers and a file
> of nine 1-bit flags.  
>  The three files of registers are the general-register file, the pointer-
> and index-register file, and the segment-register file.
>
> **8086プロセッサには、4つの16ビットレジスタの3つのファイルと、9つの1ビットフラグのファイルが含まれています。  
>  レジスタの3つのファイルは、汎用レジスタファイル、ポインタおよびインデックスレジスタファイル、およびセグメントレジスタファイルです。**
>
> 3.Segment-Register File.  
>  Programs which do not load or manipulate the segment registers are said to
> be dynamically relocatable.  
>  Such a program may be interrupted, moved in memory to a new location, and
> restarted with new segment-register values.
>
> セグメントレジスタをロードまたは操作しないプログラムは、動的に再配置可能と呼ばれます。  
>  そのようなプログラムは中断され、メモリ内で新しい場所に移動され、新しいセグメントレジスタ値で再起動されます。

* * *

ちなみに貴方と同様のアドレス拡張の考え方を採用した別のメーカーのCPUも存在していますが、それでも16ビットレジスタであり、使わないビットは0固定という方法でした。  
実際にはCPUとMMU(MemoryManagementUnit)というチップの組み合わせで、結局は実メモリ上では64KB境界にとらわれず自由に配置出来るようになっていました。

[Z8000 - Wikipedia](https://ja.wikipedia.org/wiki/Z8000)

>
> 基本的には16ビットアーキテクチャだが、組込みシステム向けのZ8002を除いてZ8001では7ビットのセグメントレジスタによるアドレス拡張を行いZ8010(MMU)で実アドレスに変換し、アドレス空間を8Mバイトまで拡張している。

[Zilog Z8000 CPU Technical
Manual.](http://www.bitsavers.org/components/zilog/z8000/Z8000Tech.pdf)  
[Zilog Z8000 CPU User's Reference
Manual.](http://www.bitsavers.org/components/zilog/z8000/Z8000_CPUrefMan_1982.pdf)  
どちらにも以下番号の説明図あり。  
Figure 2-6. CPU Special Registers  
Figure 3-3. Segmented and Non-Segmented Address Formats  
Figure 3-4. Segmented Address Translation

* * *

さらにちなみにスーパーファミコンとかで有名だけど今のWeb上にはあまり簡単にアクセス出来そうな資料が乏しい65816が8ビットのセグメントレジスタを使っているようですね。  
馴染みのある人はいっぱい居ると思われるのですが、Web上には図解とかで分かりやすい資料が乏しいようです。

8ビットの6502が256個あるようでもあり、あるいは68000の親戚のようなリニアなアドレッシングもある不思議なCPUですね。

[65816
(コンピュータ)](https://ja.wikipedia.org/wiki/65816_\(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF\))  
[WDC 65C816 - Wikipedia](https://en.wikipedia.org/wiki/WDC_65C816)  
[65816 アーキテクチャ
SNES研究室](http://hp.vector.co.jp/authors/VA042397/snes/65816.html)  
[改造ドンキーの館 - SNES技術資料 - 65C816 プログラミング リファレンス -
レジスタ](https://donkeyhacks.zouri.jp/html/Ja-jp/snes/cpu/register.html)  
[改造ドンキーの館 - SNES技術資料 - 65C816 プログラミング リファレンス -
アドレッシングモード](https://donkeyhacks.zouri.jp/html/Ja-jp/snes/cpu/addressing.html)


CC BY-SA 4.0
2020-01-04T08:07:08.827
61963
2020-01-06T03:52:05.417
2020-01-06T03:52:05.417
26370
26370
61953
answer


他の回答者の皆さんがおっしゃっている通り、不便だったり回路が複雑になったりで、4bitにするのは一顧だにされなかったというのが正しそうです。しかし、たとえセグメントレジスタのサイズを変更することを検討したとしても、メモリの有効活用の点から、4bitにすることは決してなかったでしょう。

仮にセグメントレジスタが 4 bit だったとしましょう。するとセグメントの数は 16個になります。セグメントレジスタと 16 bit
のレジスタを合わせて、20 bit の実アドレスを生成するには、セグメントレジスタと 16 bit レジスタを直結するしかありません。つまり、1M
のメモリ空間は、16個の 64K byte のセグメントに分割されるわけです。

あるアプリケーションが 32K byte
のメモリを要求したので、セグメントを一つ割り当てたとします。そのアプリはセグメントの半分しか使いません。同じセグメントを他のアプリに割り当てるわけにはいかないので、残りの半分は無駄になってしまいます。

8086 は 8 bit プロセッサから 16 bit に移行するときの CPU
ですから、数キロバイトしか使わないアプリもたくさんあったわけですが、そうなるとメモリの、ほとんどは無駄になる可能性もあります。

また、当時はメモリも高価だったので、1M フルに積んでいるコンピュータは、かなりの高級機でした。PC-9801 の初代機の CPU は 8086
互換でしたが、128K しかメモリを積んでいませんでした。4 bit
のセグメントレジスタだったら、セグメント二つ分です。全メモリ空間を二つにしか分けられなければ、メモリ管理の役には全く立ちません。

実際の 16 bit のセグメントレジスタを 4 bit シフトして使う方法なら、16 byte 間隔で 64K
個のセグメントを割り当てることができます。これにより、無駄なくメモリ管理ができるわけです。


CC BY-SA 4.0
2020-01-09T02:12:56.417
62084
2020-01-09T02:12:56.417
3605
61953
answer