8086 Segmented Memory was a good idea

(owl.billpg.com)

32 points | by billpg 1 day ago

11 comments

  • st_goliath 1 hour ago
    > 8086 Segmented Memory Was a Good Idea.

    Yet the article goes about the most ass backward way of explaining 8086 segments and constructs a convoluted mental picture of dividing memory into overlapping chunks.

    It's really, really simple: segments on the 8086/88 are 64k sliding windows into an 1M address space. You can move them around at 16 byte granularity.

    You need more than 64k for code + data? No problem, the CPU knows when it's fetching an instruction vs when it's fetching data, you can have two sliding windows: code (CS) and data (DS). Split them apart, and it's not much different than a Harvard-style machine and gives you access to more than 64k at a time.

    Still need more? No problem, the CPU has a hardware stack with dedicated push/pop/call/ret instructions and a base pointer for stack indexing. It knows when it's accessing the stack, so we can split the data window into regular data (DS) and stack data (SS). Oh, you occasionally want to copy stuff between segments or somewhere else in memory? Well, to encode 3 segments we need 2 bits anyway, let's throw in an extra data window (ES) and some DS-to-ES copy instructions.

    • gdwatson 25 minutes ago
      It was a clever hack for porting existing code. But it doesn’t scale at all – you’ve just described adding four registers to a register-starved architecture in order to solve the issue for one CPU generation or so.
      • rob74 21 minutes ago
        Plus all this pointer juggling would have been more or less ok (or not ok, but doable) when programming in assembly, but for a compiler it would have been a recipe for disaster...
  • wewewedxfgdf 38 minutes ago
    I seem to recall at the time that flat memory was self evidently a better idea. It's not like people were sitting around going "gee I can't think of any better way to do memory addressing that this" until some genius suggests "how about flat?!?!?" Everyone knew flat was best but were stuck with 8086 crap.
    • KellyCriterion 18 minutes ago
      -- Everyone knew flat was best but were stuck with 8086 crap.--

      This! Thats one of the most interesting things to me: Actually very often in the IT-world, the worst competitor won the race while better solutions were known and available: Microsoft, Intel etc.

      Esp. that MS won for decades while making mainly a very bad OS, though they have some good enterprise products.

      How would the world look, if Unix/BSD would have won this race?

      • Ekaros 9 minutes ago
        I really wonder if Unix is best we can do. Or is it also worst? So in the end two of the worst options won. It did make sense back in time. But could it have been replaced with something better later?
        • wewewedxfgdf 6 minutes ago
          >> two of the worst options won

          What do you mean, which are the two? Sure, Windows is crappy by Linus and MacOS? They are both awesome.

      • wewewedxfgdf 14 minutes ago
        Being technically best has long been known to not be correlated to market success in the way that makes logical sense to technical people who feel confused about this.
    • PaulHoule 32 minutes ago
      Personally I enjoyed writing assembly with segments. You can have 64k of code, 64k of data and 64k of stack without trying. So long as no individual data structure is larger than 64k there is no essential difficulty working with 16 bit pointers.

      When I think back I think it would be fun to have a hierarchical structure where composite data structures (think an array or hash map) are referred to with a pointer that goes into the segment register and you index inside a data structure with a regular pointer.

  • RagnarD 5 minutes ago
    I had to use it to do image processing on a 256MB image buffer back in the 1980s in assembly language. It was absolutely hideous. Give me a flat 32 bit memory address space any day (e.g. MC68000 around the same time.)
  • b800h 6 minutes ago
    I quite enjoyed using the memory segments - I thought they were quite intuitive and helped in reasoning about the machine.
  • senfiaj 43 minutes ago
    For its time it was a decent idea. Software was smaller and simpler. But today (and even before 64-bit) software is larger, more complex, we also need memory protection / isolation and more flexible memory allocation, so paging memory was not introduced for nothing.
    • flohofwoe 35 minutes ago
      > we also need memory protection / isolation

      I seem to remember that memory segments came with a permission system (read-only, read/write, execute) in 'protected mode'. Probably only added in the 286 though (I was always more of an m68k guy at that time).

      • senfiaj 18 minutes ago
        Maybe (I think it's possible in protected mode), but it still has an allocation problem, imagine there are programs A, B, C in the memory. Later, A and C are unloaded, leaving 2 free holes, totaling in 2MB. Now you want to load a 2MB program, but there is no unfragmented 2MB free block. The only solution I see, is to shift some loaded programs, which might be slow and even risky. Paging makes this problem much easier. Also, paging makes permissions and memory sharing more granular.
  • tliltocatl 1 day ago
    It might have worked better if x86 had general-purpose registers where every register could work as a segment. Or maybe just many more segment registers. But with only two data segment registers to play with and quite cubersome (and slow!) loads, most software just chose not to bother.
  • hexmiles 1 hour ago
    What is the difference between the segmentation model used by Intel and the banking model used by a lot of consoles? I've worked with the code of a couple of NES and GBC games, and while banking could be annoying, I never saw it as a particularly difficult model to follow and use. It did require more planning for the various functionality, but it wasn't even the most complex or difficult thing about developing for consoles.
    • Someone 36 minutes ago
      > and while banking could be annoying, I never saw it as a particularly difficult model to follow and use

      Segments aren’t conceptually difficult, either, but definitely could be annoying, and certainly was, if you had to access data structures larger than 64 kB.

      As to the differences:

      - you had four segment registers that you could ‘point’ anywhere, allowing you to access four 64kB regions of memory without changing them (the equivalent of bank switching) (one always was used for accessing the instruction to run, one for accessing the stack, but you could use those for other purposes, too (Could, not SHould)

      - segments can overlap. You could set DS and ES to the same value, for example.

      Segments also can be moved at 16-byte granularity. If you wanted, you could have DS address address memory range 0x0000 ≤ x < 0xFFFF and SS address memory range 0x0010 ≤ x < 0x1000F.

    • flohofwoe 45 minutes ago
      It's pretty much the same thing, except that all the memory mapping logic has moved from 'custom memory mapping hardware' into the CPU.
  • justincormack 38 minutes ago
    Wasm with multiple linear memories is basically segmented memory. Its a great security model.
  • AKSF_Ackermann 55 minutes ago
    The segment model seems clever if you assume that you never have an object that is larger than 64kb. And once you have that you need to care about segment overflow, pointer comparisons no longer work, everything now has to carry around segment+offset instead of just offset, and so on. And if you want an example of a >=64kb object - the html alone for that page is one.
    • rep_lodsb 33 minutes ago
      A lot of that is just bloat that you wouldn't have had back then. But it could still be handled by an 8086, not by storing the raw HTML in memory at all, but parsing it as it loads. Each DOM node would be its own object with child pointers, with attributes and names all converted into binary numbers of (at most) 32 bits each.

      64K of actual text content in a single node could be reached in some documents, but it's not that small, more than a chapter of a typical book.

      What was always a problem for segmented memory was graphics, at least if you wanted higher resolution than 320x200 at 256 colors. But you could have a segment pointer to each row of pixels instead of an entire image, as long as it would still fit within 1 MB (16 MB in the 286 protected mode).

      • AKSF_Ackermann 16 minutes ago
        True, graphics is a better example of a period-correct >=64k work, but the point is that there are multiple things where you don't expect the data to be that big until it suddenly is.
  • musicale 1 day ago
    Google's native client (NaCl) even used it on 32-bit x86...

    Segmented memory (on hardware that supported segment permissions) was used to good effect in Multics as well.

    • gpderetta 39 minutes ago
      x86 32 bit protected mode segments were a very different beast.
  • raverbashing 1 day ago
    No

    No, it wasn't

    It's the "great idea" that sounds great 5 min in and horrible 10min afterwards

    You know, kinda like using null as a string end character

    But more importantly it kept the x86 world for too long in that dead end that was 8086 mode programming

    "Oh if developers would just..." They won't. They haven't. And they will not ever.

    In hindsight maybe a binary level translator from 8080 to 8086 would have worked better (and be simple enough)

    • mschaef 1 hour ago
      The 8086 was a stopgap measure to accommodate the fact the iAPX432 was in the middle of turning into the disaster it did. Given the engineering resources and timelines involved in the 8086, it wasn't a bad compromise approach.

      > But more importantly it kept the x86 world for too long in that dead end that was 8086 mode programming > > "Oh if developers would just..." They won't. They haven't. And they will not ever.

      8086 real mode programming in the mainstream lasted from 1981 until 1991 or so. The last 35 years have 32-bit (and later 64-bit) flat model addressing with pages for the most part. Seems like a reasonable transition period, really.

      > In hindsight maybe a binary level translator from 8080 to 8086 would have worked better (and be simple enough)

      Part of the reason they liked the segmented model is that it was possible to set the segments to the same value and then ignore them entirely. That gave a programming model for the 8086 that was sufficiently close to the 8080 that it was possible to use a sort of cross assembler to do something like what you suggest. You could then opt into 8086 specific instructions and segmentation as you needed. (Which took a few years... the first IBM PC's shipped with as little as 16K of RAM.)

    • wewewedxfgdf 8 minutes ago
      Don't know why you're being voted down - you're correct - segmented memory was an awful nasty complex way to program and the industry was eager to see the backside of it.

      Why would someone be popping up in 2026 saying it was awesome? Weird.

    • billpg 1 day ago
      Indeed, I say as much at the end.

      But what should Intel have done? They needed a CPU that can run 8080 code but with more memory. Also it's the year ~1980 and we're limited to the technology of the age.

      A system with 64k sized windows seems unavoidable.

      If you extend the size of the address registers, 8080 code will only run in the first 64k, or require some kind of current window register.

      An 8080 mode might have worked but that would have been expensive.

      • flohofwoe 1 hour ago
        > Also it's the year ~1980 and we're limited to the technology of the age.

        Tbf the Motorola 68000 which was released around the same time (1979) had a proper linear address space with 32-bit address registers (of which 24 bits were wired up).

        Also the 8086 was intended as a cheap and temporary stop gap until Intel's "proper" 32-bit CPU architecture was ready for prime time (the doomed iAPX 432).

        • smallstepforman 44 minutes ago
          New platforms were 68000, old platforms with legacy code just wanted access to more memory, so 8086 segments allowed 64kb chunks. A hack only usable by folks that still wanted to run their old 64kb programs.

          It would be a piece of trivia today if motorola were not 6 months late which forced IBM in frustration to change tracks to Intel and MS DOS instead (which worked on 8086). That 6 month drlay created WinTel of today.

    • flohofwoe 1 hour ago
      It's not all that different from the memory pages we have today, except that the 'segment' addressing has become a lot more complex under the hood (multi-level page tables) and a lot simpler at the surface (by merging the 'segment-' and page-address bits into a single virtual address).

      PS: and segmented memory wasn't all that different from the memory banking used before in 8-bit home computers to address more than 64 KBytes, except that the memory mapping hardware was implemented outside the CPU.

      • amiga386 45 minutes ago
        > It's not all that different from the memory pages we have today

        An MMU gives you a flat addressing model. There is no comparison. 8086 segments are rigidly locked to a 64KB window that goes forward in memory 16 bytes for every segment (so segmented address 1234:5678 is linear address $12340 + $5678 = $179B8)

        It didn't do this to offer a useful feature like an MMU. It did this to allow code that doesn't know segment registers exist to think they're still running on an 8-bit Z80. What a waste of potential. The 68000 didn't pretend to be a 6502.

        The 80286 introduced protected mode with "segment descriptors", but this is well after MMUs existed on other CPUs, it didn't invent virtual memory.

        If you want to see something to make you weep, look at the MS-DOS version of unzip. It has to do all kinds of crazy, just to allocate 64KB of RAM and get all 64KB, not 8 bytes less. And it's still locked into a memory access model that will not let it ever address more than 64KB of any one object. It's why MS-DOS was viewed as a toy OS for a toy computer.

            #if defined(__TURBOC__) && !defined(OS2)
            #include <alloc.h>
            /* Turbo C malloc() does not allow dynamic allocation of 64K bytes
             * and farmalloc(64K) returns a pointer with an offset of 8, so we
             * must fix the pointer. Warning: the pointer must be put back to its
             * original form in order to free it, use zcfree().
             */
        
            ...
        
            static ptr_table table[MAX_PTR];
            /* This table is used to remember the original form of pointers
             * to large buffers (64K). Such pointers are normalized with a zero offset.
             * Since MSDOS is not a preemptive multitasking OS, this table is not
             * protected from concurrent access. This hack doesn't work anyway on
             * a protected system like OS/2. Use Microsoft C instead.
             */
        • rep_lodsb 20 minutes ago
          That's a limitation of the Turbo C library, as the comment says. DOS memory allocation functions take the size in 16-byte "paragraphs", and return a segment, with the allocated memory starting at offset zero in that segment.
    • torusle 1 day ago
      > In hindsight maybe a binary level translator from 8080 to 8086 would have worked better (and be simple enough)

      Many programs written in assembly language used self modifying code back then. It saved RAM and improved performance. All programs that used such trickery would have broken by a binary translator.