Top
Best
New

Posted by billpg 2 days ago

8086 Segmented Memory was a good idea(owl.billpg.com)
66 points | 147 commentspage 2
pif 19 hours ago|
> Need more than 64KB? Allocate two blocks.

How is that compatible with an array and a simple implementation of the index operator?

billpg 15 hours ago||
I once developed for PC-GEOS, which wanted all memory in exactly 8K sized blocks. I wrote a set of C macros that presented an array-of-arrays as a single collection by using mod/divide operations on the index.
pjc50 18 hours ago||
It isn't.

This was a problem.

peterfirefly 13 hours ago|||
You can do the equivalent of the hypothetical ADSC instruction I mentioned in another post using normal instructions. It's just that you need an uncomfortable amount.
trollbridge 16 hours ago|||
Not really. Compilers had huge pointers. They just were slower since they had to do 32 bit math.
richard_todd 14 hours ago||
The author assumes the way to keep segments going with larger memory would have been to change the amount of overlap, but it would have also been possible to make an 80286 where the segment registers were > 16bits, and everything else is 16 bits like before. Now you have extra segments that are still paragraphs apart and existing software could still function (you'd need new instruction variants to move data into and out of the enlarged portion of the segment registers.. call them ECS, EDS, or whatever). Anyway, just a thought.
justincormack 22 hours ago||
Wasm with multiple linear memories is basically segmented memory. Its a great security model.
PunchyHamster 21 hours ago|
It made fundamental mistake of starting as 32 bit memory model
justincormack 15 hours ago|||
You can use multiple segments (now, you couldnt originally)
trollbridge 16 hours ago||||
God help us all when a webpage needs > 4GB.
tlb 15 hours ago||
Some of mine do. They use WASM64 with threads to run robotics simulations.
trollbridge 14 hours ago||
That’s an “acceptable” use.
actionfromafar 20 hours ago|||
It puts some drag on bloat, I quite like it.
b800h 21 hours ago||
I quite enjoyed using the memory segments - I thought they were quite intuitive and helped in reasoning about the machine.
raverbashing 2 days 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 22 hours 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.)

billpg 2 days 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 22 hours 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 22 hours 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.

nwallin 15 hours ago|||
The Motorola 68000 was roughly an order of magnitude more expensive than the Intel 8086.
flohofwoe 22 hours 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 22 hours 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. Only the 80386 offered a 32-bit flat memory model.

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 21 hours 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 2 days 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.

wewewedxfgdf 21 hours 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.

peterfirefly 13 hours ago||
It was awesome in the sense that it was a really, really good solution to the problem they had when the 8086 was being designed:

  * we want to stay 16-bit
  * we want to make porting extremely easy
  * we want to make gradual upgrading of people's programs to >64K easy
  * we want to work well with really small memories (so don't force people to use fat pointers all the time)
  * we don't want the typical (or max non-redundant) instruction to get too long
  * we don't want an MMU
  * we don't want complicated bank switching
  * we don't want long carry chains for all address generations
  * -- but we still want a gigantic address space (for the time it was designed)!
peterfirefly 21 hours ago||
Could have been fixed with an ADC-type instruction that operated on segments.

Imagine if you could have done something like this:

   add  si, some-delta
   adsc es, 0
in order to move a seg:ofs ptr forward by 'some-delta' bytes.

ADSC (add with segment carry) would do:

   segreg := segreg + imm + 1000h (if carry)
or:

   segreg := segreg + imm  (no carry)
Maybe there should also have been an instruction to normalize a seg:ofs ptr (so the new offset was in the 0-15 range).

ADSC could have been adapted for the 286 with ease, as long as a specific layout of the segment descriptor tables was mandated (probably with 10h instead of 1000h in protected mode).

Edited slightly for clarity (ofs => imm). A normalizing instruction would be harder to do right for the 286 because you don't want to spend too many slots in the descriptor table(s) for a single memory object.

peterfirefly 13 hours ago|
btw, we only really need ADSC for the ES register.
musicale 2 days 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 22 hours ago|
x86 32 bit protected mode segments were a very different beast.
PunchyHamster 21 hours ago||
Author comes from some weird assumption that software is some annoying byproduct of making hardware, rather than a fact that the hardware is made to run software and making it easier is a goal.

It was just a hack. Hack to delay migration to 32 bit architecture. Effective one, but hack nonetheless

NoGravitas 18 hours ago|
I think it's more like marking a transition in how we thought about software.

When I was learning C, we did things at a reasonably low level. I was learning data structures, and building things like binary trees out of things like structs, and the structs were fixed-sized memory blocks holding pointers to regions of memory which were either more structs or data fields. All reasonable stuff. But we weren't writing for a particular machine. We were writing for the idea of a machine, and part of that idea was that the machine had a flat memory model. This really struck me when I compiled my homework (parse some data into a tree) on the departmental SunOS server, and it worked fine, and then took it home and compiled it with Borland C for DOS on my 386 and it segfaulted on the same data. That was when I learned to hate segmented memory, but looking back, it seems to me that I learned the wrong lesson.

I learned to write software for a lowish-level model of an idealized computer. The generation before me was always writing software for a specific computer, consisting of a specific set of hardware. The software was always the goal, but the nature of the task was defined by the hardware. Things like memory segmentation were facts about the hardware, and the available hardware varied widely at the time in a way modern hardware doesn't, really, except maybe in the embedded space.

draginol 7 hours ago||
Eh. I don't think "developers broke it". The 8086 gave us something like a flat 20-bit address space and then encoded it as a segment. Once that exists, normalizing far pointers is inevitable.

Not to do a "The Amiga was ahead of its time" thing but as a reminder, 68000 has a flat 24-bit address.

deftio 18 hours ago|
Wow.... I remember writing 8086 assembly on MASM and another assembler I've forgotten the name of, and then also doing inline ASM in Turbo C++

The segment thing and the convoluted different pointer math caused real gymnastics if you ever had data bigger than 64k... such as images.

I always thought of the segments as windows of 64k but moving between those windows, esp with the limited register set, required some real mental gymnastics.

trollbridge 15 hours ago|
Contemporary hardware rarely had images over 64k and memory bandwidth at the time made them a laughable concept.
More comments...