Hacker News new | ask | show | jobs
by st_goliath 6 hours 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.

2 comments

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.
Segment prefixes were rarely needed and you didn't need to spend any of the precious mod/rm bits on segment registers. The GPR count was limited to 8 partly because of the 3 bits allocated to specifying them and partly because of limited die space. Segment registers only added slightly to the latter cost.
Yeah, but it was probably the right call at the time.

Backward compatibility was a breath of fresh air at a time were code needed constant porting and rewriting. No two machines were alike.

It's one of the reasons the PC became so popular.

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...
I'm sure a modern compiler would have no problem with it, but in 1980 optimizer technology wasn't there yet. Modern compilers use more memory that engineers would dare dream of in 1980.

By having no problem I mean we know enough about writing an optimizer to write such a thing. I don't think any compiler does, just that they could.

Compilers in 1980 generated 64k code segments and had no other memory model.

Most people wrote assembler particularly if they wanted to use more then 64k.

Most non assembly programs were interpreted oddly enough and most such interpreters were also mostly 64k.

I think you are missing the entire point of the article (which I kinda agree with), and just repeating the popular wisdom.

In the era a machine with "object addressing" sounded like a perfectly valid futuristic design (what a Lisp machine strived to be; I guess today you would call it tagged memory of some kind). The 8086 is not that, but the original design would have allowed to evolve it into something like that.

The article's point is that since programmers simply treated it as a sliding window (instead of an opaque object handle), the plan could not be implemented, and the half-assed thing became stuck.

Having seen other Intel RISC designs, I fully agree with the premise.

But with only four segment registers, you couldn't treat it as that - not unless you only had four objects. So treating it as a sliding window was all you actually could do with it.
With 6-7 general purpose registers you could have; since anyway only three of them were usable for addressing you constantly had to load from memory. just use MOV ES instead of MOV BX to load a pointer and you actually got to increase your GPRs by one or two. Nobody did it except for larger memory areas which were allocated using farmalloc() or the INT 21h allocator.
x86 has 7 general purpose registers.

Using a bare segment register as a pointer was quite common. That’s what the DOS memory allocation call would return.