39

The 8086 used a segmented memory architecture where the linear address was computed from a 16-bit segment number and a 16-bit offset. This greatly complicated things from a programming perspective. The Motorola MC68000, designed at about the same time, used a flat 32-bit linear address space and was much easier to program.

I understand that source-level compatibility with the 8080 was a consideration but surely the CPU could have started up in, say, 8080 mode where the 16 MSBs of the address registers would be forced to zero then switch to full 32-bit (or 20-bit) addressing via a mode-switch instruction.

What exactly were the reasons the designers of the 8086 chose a segmented memory architecture instead of a flat, linear one?

  • 7
    The 68000 ran in something like your 8080 mode: it had a 24-bit address space, ignoring the top eight bits of addresses. This caused problems when the 68020 switched to a full 32-bit address space, as explained here. – Stephen Kitt Jul 8 '18 at 7:22
  • 5
    Wrong question: There's nothing wrong with base registers (which really, is what the 8086 "segment" registers actually are.) The real question you should be asking is, "Why did they think anybody would be happy with 16-bit pointers on a machine that was capable of addressing 20-bits worth of physical memory?" If the 8086 only had A1-A16 address lines, then nobody ever would have complained about the segment registers; but also, Either IBM would have chosen a different processor for the IBM PC, or else the IBM PC would have gone the way of the Apple ][ and the Commodore 64. – Solomon Slow Jul 9 '18 at 2:34
  • 2
    @jameslarge The 68k was considered for the IBM PC; preferred in fact but unfortunately the 68k wasn't fully debugged at the time the decision of what CPU to use in the 5150 was made. At decision time they had decided to go with a 16-bit (or better) processor in the PC and the 808[68] seemed like the safest bet. – Alex Hajnal Jul 9 '18 at 2:49
  • 7
    I think this quote from DTACK Grounded #10 sort of sums it up: In fairness to Intel, the 8086 was not INTENDED to be the best. It was intended to be FIRST, with downward software compatibility. – tofro Jul 9 '18 at 7:50
  • 2
    The real question is not “Why did the 8086 use …”, but “why did anyone use 8086”. It was so out of date the day that someone at IBM suggested the creation of the PC. – ctrl-alt-delor Jul 11 '18 at 13:49
73

For once, I do have a direct source for a "Why didn't they ...?" question. Eric Isaacson, back in the late '80s and '90s, wrote a commercial assembler for the 8086, called A86. (His homepage still has a section offering it for sale for $50, $52 outside North America, and explaining why it's the best assembler on the market for DOS. You can even download the extra patch supporting 80386 instructions for free.) What's of interest to us is this story from chapter 10 of the manual. The date on this copy is 1999, but the earliest versions of the document were written in 1986. I've bolded one part of this.

The (grotesquely ornate) level of support for segmentation was dictated by Intel, when it specified (and IBM and the compiler makers accepted) the format that .OBJ files will have. I attended the fateful meeting at Intel, in which the crucial design decisions were made. I regret to say that I sat quietly, while engineers more senior than I applied their fertile imaginations to construct fanciful scenarios which they felt had to be supported by LINK. Let's now review the resulting segmentation model.

[...] The scenario is as follows: suppose you have a program that occupies about 100K bytes of memory. The program contains a core of 20K bytes of utility routines that every part of the program calls. You'd like every part of the program to be able to call these routines, using the NEAR form to save memory. By gum, you can do it! You simply(!) slice the program into three fragments: the utility routines will go into fragment U, and the rest of the program will be split into equal-sized 40K-byte fragments A and B. Now you arrange the fragments in 8086 memory in the order A,U,B. The fragments A and U form a 60K-byte block, addressed by a segment register value G1, that points to the beginning of A. The fragments U and B form another 60K-byte block addressed by a segment register value G2, that points to the beginning of U. If you set the CS register to G1 when A is executing, and G2 when B is executing, the U fragment is accessible at all times. Since all direct JMPs and CALLs are encoded as relative offsets, the U-code will execute direct jumps correctly whether addressed by G1 with a huge offset, or G2 with a small offset. Of course, if U contains any absolute pointers referring to itself (such as an indirect near JMP or CALL), you're in trouble.

It's now been over a decade since the fateful design meeting took place, and I can report that the above scenario has never taken place in the real world. And I can state with some authority that it never will. The reason is that the only programs that exceed 64K bytes in size are coded in high level language, not assembly language. High-level-language compilers follow a very, very restricted segmentation model-- no existing model comes remotely close to supporting the scheme suggested by the scenario. But the 86 assembly language can support it [...]. The LINK program is supposed to sort things out according to the scenario; but I can't say (and I have my doubts) if it actually succeeds in doing so.

Note that this is discussing the software support for segmentation in the MS-DOS linker, rather than the hardware support.

Another reason that we have clear evidence for: Intel's previous chip, the 8080, supported a 16-bit, 64KiB, memory space. The dominant operating system for it was CP/M. Intel and Microsoft both made a serious effort to make the new environment as source-compatible with CP/M code as possible.

I will give examples from MS-DOS 1.0, because that was the most important and best-documented OS that took advantage of this feature. Back when the ISA was being developed, IBM had not yet chosen the 8088 for its Personal Computer Model 5150, there was a large library of 8-bit CP/M software, and memory was even more expensive, all the considerations I am about to mention were even more crucial.

The segmentation scheme allowed an OS for the 8088/8086 to emulate an 8080 running CP/M with minimal hardware resources. Every MS-DOS program was initialized with a Program Segment Prefix, which just like it says on the tin, was loaded at the start of the program segment. This was designed to emulate the Zero Page of CP/M. In particular, the 8080 instruction to make a system call in CP/M was CALL 5. If you use that instruction in a MS-DOS program, it will still work. The Program Segment Prefix will be loaded into CS, and CS:0005h contains a jump to the system-call handler of MS-DOS.

Segmentation effectively gave every legacy program its own 16-bit memory space, allowing it to use 16-bit pointers as it always had. This both saved memory and saved 8-bit code from needing to be extensively rewritten. (Recall that most software today runs on 64-bit CPUs, but ships as 32-bit programs because smaller pointers are more efficient; this was even more crucial on an original IBM PC model 5150.) A .COM program was based on the executable format of CP/M, and got by default a single segment for code, data and stack, so a program ported from CP/M could treat the 8086 as a weird 8080 where it had the whole 64KiB of memory to itself and the registers had different names. MS-DOS 2.0 let programs start with separate segments for their code, stack, data and extra data, still using 16-bit pointers and offsets. Of course, a program aware of the full 20-bit address space could request more memory from the OS. In MS-DOS, it could request memory in 16-byte "paragraphs" (bigger than a word, smaller than a page) and would get them in a new relocatable segment, whose exact value it did not need to care about or waste a precious general-purpose register to store. (Unlike shared libraries for the x86 and x86_64 today!)

But why not shift segment registers 16 bits to the left, instead of four, for even less complexity, and let programs use only the lower-order 8 or 16 bits of a 32-bit address space, for offsets within the current page of memory? The apparent advantage is that it allowed segments to be aligned on any 16-byte boundary, instead of a 65,536-byte boundary. Any program back then needed to use a lot less than 64KiB of memory, and exceptionally few computers even shipped with the 256KiB that the CS, DS, ES and SS registers could address. The OS, the program in the foreground and every program to Terminate-and-Stay-Resident could not all have gotten their own 16-bit address spaces, much less separate ones for their code, data, and stacks, if every segment had needed to be on a 64KiB boundary. But, with the memory model Intel used, programs could use 16-bit pointers with much smaller memory blocks.

Finally, remember that gigabytes of memory was a preposterous figure in 1976. Intel correctly realized that they'd have plenty of time before it was ever worth worrying about needing 32 bits of address space. Even their 80286, generations down the line, only supported a 16-MiB address space and allowed 16-bit near pointers. What they didn't foresee was that their 8086 ISA would ever become as dominant as it did—and that they'd be stuck with it, in a market that demanded 100% compatibility.

  • 2
    Now that's an interesting find. Bookmarked. Thanks a lot. Nonetheless, I find it a bit strange to argue with the 1981 IBM-PC and its software constrains to explain a the decisions made in 1976. Isn't it? – Raffzahn Jul 8 '18 at 20:36
  • 2
    @Raffzahn I do not know when that story was added to the A86 manual, other than that it was between 1986 and 1997 (the earliest copy on archive.org). From the reference to IBM, he was probably writing in the early '90s about a meeting circa 1980. – Davislor Jul 8 '18 at 21:34
  • 9
    why [A86 is] the best assembler on the market for DOS ... random offtopic remark: the somewhat expensive licensing for it (from my perspective at the time as an 18-year old student) was one of the primary reasons that the actual best assembler on the market for DOS (i.e. NASM) ended up being written. :) – Jules Jul 9 '18 at 4:33
  • 2
    @Jules I've used it! Thank you. If I were motivated to complain about a86 today, I would probably.point out that being able to compile a huge number of simple statements per second is not useful if, as he says, asm programs larger than 64K do not exist. And TASM is worse because it does support more complex syntax? But, it's charming that that page from the 20th century, which was already retro when it went up, is still there. – Davislor Jul 9 '18 at 5:10
  • 5
    @Buge No, they didn't. Not for at least 10 years to come when the 8086 was designed. – tofro Jul 9 '18 at 8:42
26

The 8086 used a segmented memory architecture where the linear address was computed from a 16-bit segment number and a 16-bit offset. This greatly complicated things from a programming perspective.

I beg to differ. Using segments doesn't 'complicate' things in any way. Sure, it may require a different style of structuring the data used and there are very few cases, in real world applications, where pointer arithmetic is needed.

The whole issue is a bit like a NYC cabby crawling bumper to bumper on the FDR and complaining about the speed limit on highways and how great the German Autobahn is. While right in theory, there is no practical implication as his job will never let him use this advantage - even if he moves to Europe and becomes a Taxi Driver.

The Motorola MC68000, designed at about the same time, used a flat 32-bit linear address space and was much easier to program.

No so sure. Mind you, that not only Unix was originally designed segmented (and C still carries this over), but as well the (original) MacOS. Here a user application had to make OS calls for dereferenceation all the time to allow its memory management to work. The flat 68k address space is maybe nice for embedded programs or cases where the simple assumption of one programmer, one program and one machine works out, but not in a more sophisticated environment.

I understand that source-level compatibility with the 8080 was a consideration but surely the CPU could have started up in, say, 8080 mode where the 16 MSBs of the address registers would be forced to zero then switch to full 32-bit (or 20-bit) addressing via a mode-switch instruction.

That would have restricted the machine to an emulation mode, where converted Software could only use a single 64 KiB address space, leaving the rest of memory dormant. And only one such program could run at a time. So effectively removing every reason to switch away for an existing 8080/85 system.

Unless one invents some kind of relocation mechanism that is. Like having a process pointer to give separate 64 KiB address spaces to each program, or the ability to address additional memory beyond 64 KiB with some banking or such... oh, wait, that's exactly what segments do.

Keep in mind that 8085 source compatibility is not a feature in itself, but a request to satisfy customer needs. And one of the biggest needs was to allow more code to be handled (and maybe a bit more data *1). The issue of source code compatibility is often seen as a rather easy thing. Just converting some instructions into equal and that's it. But software also and eventually foremost means data structures. A part that often needs more than a few key presses to be adapted. The instruction mix of the 8086 had for (next to) all 8080 instruction a functional equivalent. While the code representation (binary) may change not only in content but also in size, data structures and their interaction could be replicated without any change.

Adding segment registers offered an easy way to port application with only a few added lines to the 8086 and enabling the use of 64 KiB code plus 64 KiB data (*2). Depending on the applications call structure this could be extended to several hundret KiB of code

As well important is complexity of the CPU itself. The 8086 is a very clean 16 Bit CPU. There are no 32 bit operations (*3) except to optimize far pointer loading. Unlike the 68k with an outright bloated code requirement for handling 16 and 32 bit data types. Not the least reason why 8086 did outperform the 68k in real applications at comparable speed rates (*4).

So, why spending more than double the transistors (*5) on a more complex CPU design that yields less performance? For a feature that is hidden by compilers anyway?

What exactly were the reasons the designers of the 8086 chose a segmented memory architecture instead of a flat, linear one?

It's easy to count several good reasons:

(A non exhaustive list what just came to mind. There might be many more to be found by spending more time to think about)

  1. First and most important, it's a clean 16 bit CPU. There is no need to handle any other data type (beside byte for memory access).

  2. KISS.

  3. Easy port of existing 8080/85 software due a virtual maximum data type of 16 bit for pointers.

  4. Extension of available code space to full 64 KiB without modification

  5. Easy extension of available code space (with a minimal level of modularization) for existing (ported) software.

  6. Extension of available data space to full 64 KiB without modification

  7. Speed. By reducing the majority of pointer operations to 16 Bit instead of 32 on a 68k (*6)

  8. Speed. By reducing code size due a restriction of all code and data pointers to 16 bit. After all, more compact code needs less bus bandwith, leaving more for real work.

  9. Simple memory management for multi tasking

  10. Simple memory management for multi programming

  11. Support existing complex OSes like Unix

and quite important (and to make the dozend full):

  1. (well behaving) 8086 application can run seamless in a (future) virtual memory environment without any modification.

It might be useful keep in mind that in 1977 mini systems were still build (and bought) with 64 KiB RAM or less. Even a small memory model application (64 KiB for each segment), couldn't be handled by such. Here the 8086 was quite at the height of time. Segmented memory was the way to go. At that time next to all classic 'flat' architectures had reached their EOL. Eventually except the /370, but it might not count as realy flat due its general base+offset addressing scheme.

Long story short, the 8086's segmented scheme was not only on the heights of its time but also a very efficient and foreward looking design.


Addendum: There might be many details to critisize of Intels design decisions in hindsight, like supercat (*7) favouring an 8 bit offset (instead of 4), and some may look quite appealing (*8), still the 8086 did include a remarkable lot of features in a very small and limited design, making it back then a huge success outside the (later) PC market. x86 Unix systems did outsale 68k based ones by a magnitude, especially due its early ability to handle a large physical address space via segmentation.


*1 - The main market for 8080/85 systems were not dektop computers, but embedded systems. Desktop users were in 1977 not only a real minority, but also still happy to have even some memory, with full 64KiB being a dream for the wealthy. Complex embedded systems in contrast did already back then scratch the 64 KiB limit.

*2 - The additional stack segment doesn't really count, as such application would only need a rather meagre amount of stack.

*3 - For nitpicking, there is multiplication and division as 16x16 and 32x16

*4 - At the same clock rate a 80286 outperforms a 68000 by about 20%

*5 - An 8086 got ~29,000 transistor functions, while the 68k is said to have 68,000

*6 - Not to mention that the 68k here always had to shovel a 33% overhead

*7 - Part of this chat. mschaef did make a similar comment as Alex Hajnal reminded. Alex is a serious data archeologist :)

*8 - When thinking about the 8086 and its memory management I'm usually rather satisfied what has been made possible, as the segmented aproach is quite useful for multi programming (and multi tasking as well). I can only blame the designer(s) for not having thought a tiny little step ahead for a by adding support for a software managed MMU supporting memory protection and swaping. All the hardware needed would have been 4 segment size registers(SSR), 4 16-bit-wide OR gates and one comperator active during EA generation.

Whenever an EA is calculated and the appropriate SSR register is non zero (checked via the OR gate) the resulting EA gets compared to its SSR. When low or equal processing continues, when higher a 'Segment Violation' Exception happens - much like INT 0Dh later on the 286. Now a some (OS) handler can decide what to do.

Similar all instructions loading any segment register (or SSR) would (when segment checking is active) issue a 'segment check' exception. Again like the 'Segment Not Present' (INT 0Bh) on a 286 (or the whole 0Ah/0Bh/0Ch group). As well an OS handler could check if the new segment value is one assigned to the program.

Whenever an exceptions happens the checking is disabled to allow the handler to act as needed (which also would make disabling it quite easy for an OS without memory protection by adding a NOP handler to kill any checking that got activated by 'accident') and must be switched on again before returning.

With this all need for a protected mode OS would be present. Sure, segement switching would be rather slow, compared with a hardware solution like with the 286, still better than noting and at minimal additional cost. Not to mention that if DOS had used this feature, many ugly programs and even less programming styles, would have prevailed :))

  • 8
    Don't forget space. An architecture where application code was expected to keep track of 32-bit addresses by default would mean that pointer-intensive programs suddenly need twice as many (expensive-at-the-time) kilobytes to store their data in. – Henning Makholm Jul 8 '18 at 14:15
  • 3
    I really do not know how you can argue that the segmented memory is simpler than a flat address space. It's simply false. The argument about support for Unix is also wrong. Unix likes a flat address space, not that the 8086 could support Unix with no virtual memory management or memory protection. That simply wouldn't have been a concern for the 8086 designers. – JeremyP Jul 9 '18 at 11:03
  • 5
    Having started my professional career on the IBM 370 in 1974, I assure you that segmentation did complicate things for me. A flat address space (like on the CDC 6600) was easier to work with. – David Thornley Jul 9 '18 at 18:05
  • 1
    @RBarryYoung Serious? You mean, with introduction of the VAX every other mini instantly vanished? Someone should have told that DEC, as they where sellings many michines with less than 64 KiB way into th 80s. Maybe not VAX11/780, but many 11 with as low as 8 KiB (11/03 @ 2100 USD in 1980:)) – Raffzahn Jul 9 '18 at 19:14
  • 1
    @Raffzahn I think your *7 is here – Alex Hajnal Jul 9 '18 at 20:10
11

I am pretty sure the Intel engineers just weren't there, yet. And they were pressed by the market to push out a 16-bit CPU before all the others did to keep the market share they had already lost big time to small Zilog. (I am pretty sure that the design of the 8086 was much more driven by marketing pressure TTM and compatibility constraints than engineering creativity).

The x86 CPU was (opposed to the Motorola 68k) a backward-looking architecture that was designed to be able to re-use as much as possible from the 8-Bit 8080 world (both in terms of hardware, like peripheral chips and in terms of software, like the bulkload of CP/M software that was available for the 8080 - And - but this is only an assumption: As much as possible from chip-level building blocks. And such chip-level re-use is just much simpler achieved by a segmented approach than starting a flat-32-bit model from scratch like the 68k did). Note the Zilog 16-bit-CPUs chose a very similar approach that was even less radical.

I think the best indication for how desperate people were looking to hold on to the CP/M ecosystem at that time is actually a non-Intel product: The NEC V20 that even 3 years after the 8086 came with a re-engineered 8086 core and full 8080 emulation.

Your claim the original 68000 were a "non-segmented" architecture is only partially true. If you wanted to use one of the main features of the 68k, fully position-independent code that was very important for systems not employing an (at that time) expensive external MMU (or wait for the 68020 that lifted the limitation to 16-bit index registers), you deliberately decided to segment your memory into 64k chunks that could be reached by register-relative addressing. MacOS did that initially, and other systems like the Amiga and the Sinclair QL as well.

  • 5
    Right — Stephen P. Morse himself said that the 8086 was a stop-gap design, intended to give Intel a general-purpose 16-bit CPU with a decent migration path from the 8080 to address market requirements while the real long-term CPU was being worked on (iAPX 432). – Stephen Kitt Jul 8 '18 at 13:34
  • 1
    @Raffzahn I don't think so - While your answer is looking into technical aspects (which is fine), it completely ignores the situation on the semiconductor market in the early eighties - which I am trying to address. It's obviously hard to come up with rock-solid facts in retrospective on what drove Intel to produce such a design, but it still needs to be looked into. I'm trying to ignore the "argumentative rant" bit here, as I find it a bit on the offensive edge. – tofro Jul 8 '18 at 16:22
  • 2
    @Raffzahn it doesn’t explain anything about the segmented design, no, but it does explain why there wasn’t much thought put into long term evolution of the design (at least, on that part of the design). – Stephen Kitt Jul 8 '18 at 17:26
  • 1
    @Raffzahn I agree that the segmented design had its benefits, but I do think that it would have been implemented differently if the designers had realised it would survive for 30-odd years — for one, they might have allowed the multiplier to be adjusted... (Although really I think any argument around the x86 and its design needs to focus more on the longevity of DOS and its 16-bitness rather than perceived failings of the x86 itself — if we’d switched to 32-bit OSs in the late 80s with the 386 we’d have been much better off.) – Stephen Kitt Jul 8 '18 at 18:31
  • 1
    The Amiga did nowhere divide the memory into 64k chunks. The decision to use smaller segment sizes was just a compiler option. You can write 68000 position independent code with larger segments, even without a dedicated addressing mode, it just implies a bit more complicated code. But Amiga applications were never required to consist of position independent code anyway, as the executable format allowed to post-fix absolute addresses after loading. – Holger Jul 9 '18 at 9:31
7

The 8086/8088 is designed to be a 16-bit CPU which means that its registers are all 16 bit wide. You can address 64kB with a 16-bit pointer, but the designers wanted to address more. So what are the options?

You can add special registers that are larger than 16 bits. This would have complicated a lot of things: increasing all registers would have been expensive and hindered porting existing code (easy porting from 8080 was an explicit design goal), mixing 16-bit and larger registers would have been cumbersome (and likely also expensive and hindering portability). Further, a more complicated design would have delayed the project and Intel wanted the 8086 to get to market fast (the 8086 was seen as a temporary solution by Intel at the time, as far as I can remember).

Or you can divide pointers into two parts. This is what Intel has chosen: it was a simple solution to get 20 bit pointers. Theres a dedicated adder in the BIU (Bus Interface Unit) which simply shifts one 16-bit value by 4 to the left and then adds another 16-bit value. This was very simple to implement and also fast. As mentioned it other more detailed answers, it also made it easy to port 8080 code. It's a "cheap" solution to address more than 64kB on an 16-bit CPU and was a good fit for the design goals of the 8086.

  • Having registers that are slightly bigger than 16 bits is hardly impossible--it's perhaps the second best approach to addressing ~1MiB of address space--loading and storing such registers is often a lot more expensive than dealing with 16-bit registers. Unless an individual object exceeds 65,520 bytes, adding a displacement to a pointer to part of it will require a 16-bit read-modify-write cycle. Doing a read-modify-write on a linear 20-bit pointer would require reading and writing 3 bytes or two 16-bit words--much more expensive. – supercat Jul 10 '18 at 19:26
5

Source code compatibility (via assembly language translation) with the 8080/8085, as mentioned in the question, was a major design consideration with the 8086. To bootstrap the usefulness of the processor and get it into real systems as quickly as possible, allowing producers of existing software (especially CP/M) to get that software to work on the 8086 almost effortlessly was critical.

However, as we've discussed here before, the conversion process needs to replace some single byte instructions on the 8080 with multiple byte instructions on the 8086. Therefore, a program running on CP/M-80 that used the full 64KB of RAM couldn't run inside a single CP/M-86 16-bit segment, as its code may well expand to a large enough size that there's no longer enough space for its data. In order to allow easy conversion, there needed to be a way of separating the code and data segments to allow more memory than 64KB to be used by a single process, without needing to change data formats by using pointers longer than 16 bits (which would disrupt source compatibility for programs written in assembly language, which many of the big CP/M programs were).

The segmented model allows a program to set its CS and DS/SS registers to different values and therefore trivially expand from 64KB maximum to 128KB maximum. Doing so simply requires the addition of a very short piece of code to the process startup, making it easy to add without needing to disrupt the existing code. Using a 32-bit offset register or something similar could have worked too, but would have been more complex and wouldn't necessarily have made the processor any more useful, at least in the near term. And because nobody was expecting a microprocessor design to last as long as the 8086 eventually did (there had never been anything even remotely as long-lived designed before it), the near term was all that was considered.

3

There's another point I haven't seen anybody mention.

When Intel released the 8086, they were already working on the iAPX 432.

Intel's intent was that the iAPX 432 would be the CPU that would become popular in the desktop market. They were putting an immense amount of time and effort into the design.

At least from what I've heard from a few former Intel designers, the 8086 design was a direct result of that--the 432 was taking quite a while, and Zilog was doing well with the Z80, so Intel thought they needed a follow-on to the 8085. At the same time, they wanted to ensure against the 8086 (and successors) from dominating the market to the point that the 432 would never be able to gain any significant market share.

To that end, they designed the 8086 specifically for higher-end embedded applications. Typical embedded applications rarely did the sorts of things that were clumsy and difficult with segments, and using segments usually allowed somewhat denser code, which was quite important for embedded use.

So, to some extent they failed by succeeding, so to speak. Despite their attempt at crippling the 8086, when the 432 became available, it had exactly the problem they'd feared: the 8086 (and successors) already dominated to the the point that most people have never even heard of the 432, not to mention using it. Worse, the 432 was late to market, did poorly in benchmarks, and the early iterations were fairly buggy to boot. Intel didn't officially give up on selling the 432 until around the 386 time frame, but there's no real room for question that it was an absolute flop, for exactly the reason they'd feared and tried to plan against.

  • The 8086 is inefficient at trying to work with monolithic objects greater than about 65,520 bytes, but its segmentation design is, by a considerable margin, the most efficient 16-bit architecture I know of for working with objects smaller than that which are placed arbitrarily, or better yet on arbitrary 16-byte boundaries, within a larger-than-64K address space. – supercat Aug 8 '18 at 21:54
  • @supercat: Yup--or to consider what that ends up meaning: it works well for embedded applications, but poorly for desktops, exactly as it was designed to. – Jerry Coffin Aug 8 '18 at 22:08
  • There weren't really a whole lot of desktop applications for the PC that used monolithic objects bigger than 64K which wouldn't have benefited from being processed in smaller chunks. A text editor that limited individual lines to 65,535 bytes, for example, and required them to be aligned to a segment boundary, could keep a list of N lines' start addresses in 2N bytes, and be much faster than one which operated on the entire buffer as a monolithic blob, even on a processor that could support the latter. – supercat Aug 8 '18 at 22:18
  • @supercat: I haven't written such an editor, so I hesitate to opine on it, but at least offhand, it seems like it would depend heavily upon what you were doing. For example, inserting a number of empty lines in the middle of such an editor at least seems like it would be substantially slower than doing the same in a split-buffer editor. – Jerry Coffin Aug 8 '18 at 22:31
  • The most serious problems with the 8086 segmentation design were the lack of a third general-purpose segment register, the inability of many languages to really support it efficiently, and the failure to implement a model that could designate a range of segments to use a different scaling factor. The 8086 design could have been extended to a 16MiB address space in a fashion compatible with most existing code, and the 80386 design would have benefited from a mode where the lower portion (maybe 28 bits) of 32-bit segment descriptors would be shifted by an amount controlled by the upper portion. – supercat Aug 8 '18 at 22:36
1

It is convenient to be able to address data as separate from code. It is convenient to be able to set aside space for the stack so that you can guarantee that it won't overrun anything too.

This arrangement means that the same 16 bit pointer operations (save, load, 16 bit increment) can still be used as in the i8088, but the address space is still increased.

  • Your second paragraph seems to imply to me you assume the 8086 was a successor of the 8088 - It's actually the other way round. – tofro Jul 8 '18 at 16:33
  • I can't really see why you think there were any compatibility considerations in the design of the 8086 with the 8088 that was not bound to exist until about 1 year later? – tofro Jul 8 '18 at 16:56
  • 1
    Look at the 68k family with the 68008 (which is pretty much the same thing in the 68k world as the 8088 to an x86) - It doesn't use segmented addressing, it rather is a fairly exact copy of "the real thing". Internal register layout doesn't have a lot to do with how the bus looks like. – tofro Jul 8 '18 at 17:11
  • 3
    The major difference between the 8086 and the 8088 is the data bus width; 16 bits in the 8086, 8 bits in the 8088. (That and, I think, instruction cache size; I seem to recall that was 8 bytes in the 8086 but only 5 bytes in the 8088, but could be wrong on the specific numbers.) For the programmer, even one working in assembly, the 8086 and 8088 are identical, irrespective of segmentation or memory model in use; the only difference from a software point of view is their speed in practice (even when both are clocked at the same rate). Particularly here, both have a 20-bit address bus. – a CVn Jul 8 '18 at 17:32
  • 1
    @MichaelKjörling There wasn't a cache in either, but a 5 (8088) or 6 (8086) prefetch queuein the BIU. When there is an unused bus cycle (or the CPU needs an instruction and none is ready - which is the same), the BIU will fetch ahead from CS:IP. The size is defined as 5 to hold the longest possible instruction (which is 4 on a classic 8086) plus 1. Prefixes except for REP don't count, as they are handled by the BIU. Since the 8086 data bus is 16 bit, its queue must be one byte longer to hold a possible overflow. – Raffzahn Jul 8 '18 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.