25

In 8086 architecture memory is addressed by segment:offset scheme, where the 20-bit linear address is formed as address=segment*16+offset. This looks needlessly complicated and doesn't allow to further extend physical address width without changing instruction set, despite the logical address having two 16-bit components (and 16+16>20).

A much simpler way seems to be address=segment*65536+offset. Also, in this case it'd be trivial to extend physical address width — by simply giving meaning to higher bits beyond originally used (lower 4 bits of segment and 16 bits of offset). Also, in such a case the CPU wouldn't even have to perform any addition to form the physical address.

Why was the actual address formation scheme chosen instead of the more straightforward one? Was it meant to say something like "any extension must be radical", like a change to 80286 addressing model?

1
  • 4
    Maybe something as a 256 scaling, offering 16MB of RAM could have been more sensible. 1MB was a lot of RAM at that time. Using overlapping segments makes memory use a bit more efficient.
    – TEMLIB
    Jun 25, 2016 at 19:29

3 Answers 3

34

Wikipedia says:

According to Morse et al.,.[5] the designers actually contemplated using an 8-bit shift (instead of 4-bit), in order to create a 16 MB physical address space. However, as this would have forced segments to begin on 256-byte boundaries, and 1 MB was considered very large for a microprocessor around 1976, the idea was dismissed. Also, there were not enough pins available on a low cost 40-pin package for the additional four address bus pins

Note the 8086 was a originally intended as Intel's rather quick shot at competitor's announced 16-Bit processors. So it had to re-use a lot of existing components. In addition to the reasons mentioned by Wikipedia, I guess the original segment architecture was intended as a sliding window of 64kB over the 1MByte address space. The segment register shift determined the granularity at which the window could be adjusted. So it was a trade-off between adjustable window granularity and addressable memory space - Given it was 1976, I guess 1MByte was considered an astronomically high amount of memory, and the amount of pins was a strong argument as well.

4
  • I think the answer would be even better if it linked to the particular wikipedia page from which you took the quote.
    – Ruslan
    Jun 26, 2016 at 6:15
  • 1
    @Ruslan I added a link to the relevant part of the Wikipedia article. The linked document is very interesting (and has been linked here before). Jun 26, 2016 at 7:56
  • @StephenKitt The linked document claims in table 1 an address bus width of 16 for the 8086. I think this is wrong and should be 20.
    – tofro
    Jun 26, 2016 at 9:19
  • @tofro I agree, the 8086 definitely had a 20-bit address bus (partially multiplexed with the 16-bit data bus). Figure 3 in Morse's document shows the 20-bit memory address latch. Jun 26, 2016 at 13:18
10

Using a scale factor of 16 means makes it convenient to work with objects up to 65520 bytes located on any 16-byte boundary. High-level languages don't support the concept very well, but when using machine language, rounding object sizes to 16-byte multiples makes it possible to use two bytes for object addresses rather than four. If the scale factor were larger, one would either have to round objects up to multiples of 256 bytes (rather than 16) or use 4-byte pointers (which many languages end up requiring anyway).

2
  • Indeed, this allows to save memory by reducing {1. address size}, {2. minimum object size}, compared to a larger shift. It seems in fact that C could be implemented in this way (if we limit max object size to 64K).
    – Ruslan
    Jul 21, 2016 at 19:37
  • 1
    @Ruslan: One could write a Standard-compliant C compiler in which all structures are required to be sixteen-byte aligned, but that would not represent a very efficient use of memory. What's needed is to have separate types for "pointer to anything anywhere" [4 bytes] and "pointer to segment-aligned object" [2 bytes] but C has no such concept.
    – supercat
    Jul 21, 2016 at 21:04
2

I don't think your scheme is any more extensible than Intel's. It's easy to see how to widen the address space in Intel's scheme: just increase the shift value in later generations.

Of course, this will break software that tries to do arithmetic on segments assuming that the addressable space is and always will be 1 MiB, instead of treating them as opaque values to be manipulated only via OS calls and dereferencing. But your approach has the same problem. Look at the 68000: it had 32-bit address words and a 24-bit address space, and programmers used the top 8 bits of pointers for other purposes, making it difficult to extend the address space later on.

In your approach, as soon as programmers notice that segment values are always in the range 0 to 15, they'll pack them into bytes instead of words, because why waste space? And they'll use the high 4 bits of those bytes for other purposes too. When it comes time to increase the address space, there will be at least one widely used piece of software that did that, and the company that made it will be defunct or just decide it's economically infeasible to fix it, and no one will want to upgrade their hardware because they're more interested in working software than in the hypothetical benefits of future software with access to a larger address space. After all, you don't need a larger address space to access more RAM, you just need a bank-switching scheme. Sure it's ugly but it's compatible.

That's what always happens when platforms try to design for expandability.

I don't see any other advantage of your scheme that's significant enough to prefer it over what Intel did. Intel's system has an obvious advantage in terms of allocation. If you have two 40K segments, you can just put them right after one another. With 64K paragraphs, either you put the segments in separate 64K regions and hope that you'll be able to fill in the gaps with 24+24K of other data, or else every piece of software, even if it fits in 64K, has to work with far pointers and segment arithmetic just in case it's loaded spanning a 64K boundary.

Programming for a system whose registers are narrower than its address space is always going to be a pain. People blame the 8086 segment model for the problem, but it's not the problem, it's an attempt at a solution – and I think it works about as well as anything could have.

5
  • AMD took a nice approach to solving this abuse of higher bits problem in AMD64: they require the addresses referenced to be canonical (i.e. all higher bits are equal to the most significant of the "useful" bits), or else #GP will happen. So this isn't unsolvable.
    – Ruslan
    Jul 12, 2020 at 21:09
  • @Ruslan if 68000 has done that, programmers would just have masked off the top bits before dereferencing, so their code would have been slower and still incompatible. To the extent this hasn't happened with x64 I think it's just because there's less interest in general in optimizing memory use these days, not because people are scared away by the GP fault. Also, in the 68000 era there wasn't any obvious way to fail on an invalid address (I guess you could treat it like division by zero or something).
    – benrg
    Jul 12, 2020 at 21:16
  • Why would they be incompatible? They would just be limited to low memory. And also don't forget about the kludge of A20 gate that was necessary, and was implemented. A similar way could be used if the time to extend segment values came.
    – Ruslan
    Jul 12, 2020 at 21:19
  • @benrg: The 68000 could perfectly reasonably have had any access where the upper 8 bits don't all match trigger a trap 1 (bus error). They didn't invoke that trap, but they did have a trap number designated for bus error.
    – supercat
    Jul 13, 2020 at 15:18
  • @benrg: My beef with the 80286 is much stronger than with the 8086. If the 80286 had arranged to have each segment selector consist of an 8-bit selector and 8-bit offset which would be scaled by a value specified in the descriptor, that would have improved performance of many programs (since changing between selectors associated with the same descriptor wouldn't require loading a dscriptor).
    – supercat
    Jul 13, 2020 at 15:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .