Hacker News new | ask | show | jobs
by hnlmorg 7 days ago
16 bit programs used 16 bit addresses, generally speaking.

Even with 32bit systems where you’d want more than 4GB RAM, application software still had 32 bit addresses (and thus 4GB memory limit).

I think it was a lot more common for 8bit systems to allow for 16 bit addressing though.

It’s been a while though. So hopefully I’m not misremembering things.

4 comments

You had to deal with two flavors of pointer, near and far. Far pointers came with segment selector, for accessing more than 64k. Your choice of memory model influenced the defaults. You might use near pointers for internal references in a module, and far pointers for external references.
I guess it was awkward to use languages that had higher level than assembly in order to write 16-bit programs that required more than 64KiB of memory. And also not quite portable, since they were all tied to x86 CPU. Those were messy times I guess. A somewhat similar story was 32-bit PAE, where the the CPU could address more than 4GiB physical memory, but software was still 32-bit and virtual addresses were capped at 4GiB. Linus was right that you must have more virtual memory (preferably 10+ times more) than physical, otherwise you have to jump through hoops. https://cl4ssic4l.wordpress.com/2011/05/24/linus-torvalds-ab...
"portable" used to mean "able to be ported" rather than the "comes automatically ported if you just change compiler options" that it means today
All software is portable by that former definition.

When people talked about portable before, they meant code that used an abstraction that was platform agnostic. And that’s how it’s still used today. It’s just we have better abstractions now so our expectations of what is “portable” have gotten stricter.

Eg the P in POSIX (which is nearly 40 years old now) is “portable”. The point of POSIX was to provide common abstractions that one could build against to run on multiple different operating systems. It wasn’t about porting software, it was about preventing people from needing to constantly write platform-specific ports.

It was about making software easier to port. You still couldn't necessarily just write software for all operating systems at once, but you had less porting work because less stuff was different because of the standardisation. So open(argv[1], O_RDONLY) works on all POSIX systems, but if you want to create a pseudoterminal, it's different on each, and if you want to create a container, they don't even use the same concepts.
> but if you want to create a pseudoterminal, it's different on each

This is somewhat outdated information. POSIX.1-2001 added "posix_openpt" to create a pseudoterminal, and most POSIX implementations now support it–at least Linux, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, z/OS, AIX, HP-UX, QNX, Minix and Cygwin do. (Of course, that's only true of current versions, if you go back a decade or more you'll find many of them hadn't implemented it yet.)

But you’re now arguing the same point I am: Portable means low effort porting.

Saying something “can” be ported doesn’t make it portable. People would port games from the NES to the Master System, to 8 bit Micros but in most cases they were effectively complete rewrites because there wasn’t any common abstractions between those platforms.

Where as tools like POSIX provided abstractions to make code portable.

As I said before, the only reason you think the term has changed over the years is because the abstractions have gotten better and thus people’s expectations for how much effort should be required to port have gotten stricter. But that doesn’t mean the term means something totally new.

And by the way, I have authored portable terminal emulators and $SHELLs. ;)

> I think it was a lot more common for 8bit systems to allow for 16 bit addressing though.

The 6502 and Z80 could use 16 bit addressing to access up to 64kb of memory. The 6502 had various other addressing systems, including iirc 8 bits, but none of them were wider tha 16 bits.

> The 6502 and Z80 could use 16 bit addressing to access up to 64kb of memory. The 6502 had various other addressing systems, including iirc 8 bits, but none of them were wider tha 16 bits.

Many 6502 and Z80 systems used bank switching to support more than 64KB of memory. That way you could have 128KB or more physical RAM in a machine with an only 16-bit address bus. MP/M–the multitasking/multiuser version of CP/M–had support for this as a standard feature, since it was hard to fit multiple processes/users into only 64KB; it was ported to the single-user/single-tasking version in CP/M 3.0

Essentially, this was doing virtual memory, not inside the CPU, but in one or more external chips. Actually, back in the 70s and 80s, it wasn't uncommon for a memory management unit (MMU) to be a separate chip (or even PCB) rather than an integrated part of the CPU–for many systems it was an optional add-on if you needed more memory, or wanted to run more advanced operating systems.

Oh yeah. I had loads of 6502 and Z80 systems (still do in fact). Can’t believe I forgot about that!

Though in fairness, I do mostly now just use those systems to teach my kids BASIC

Just curious how do you teach kids BASIC. I’m sure my 6 year old won’t sit tight.
I usually start with game: guess the number.

The computer generates a random number between 1 and 100. And you have to guess. When you’re too high, the computer says “too high” and likewise when you’re too low.

It’s a great starter program because it teaches you strings (the output printed), integers, comparisons, conditionals, and iteration (you keep guessing until you get it right). And the whole thing only take around 20 lines (give or take).

Then the kids plays a few games of that.

And after the novelty of that game wears off, I tell them to customise it however they want. Eg different messages, different ranges to guess from, etc.

It’s the same way I teach Python to primary school / kindergarten kids.

The nice things about this is even if the kids don’t learn and remember the basic primitives, they still get a feel of “proper” coding in the same way that we did when we grew up. And they still get something they can play, even if the game itself is super basic (no pun intended).

I’m not saying this will work with every child, though. All kids are different. But it’s been super successful both at home and in the schools I’ve helped out at.

Thanks! This is a good idea. I was thinking about typing games and such because he needs to learn words before doing anything useful, but guessing games are definitely fun, too. I can definitely write simple games using QBASIC (was preparing a Dospian on Rpi 4 as his 6 years old birthday gift).

Do you have any blog, or any recommendation of books to read for such topics? Maybe I can find some "Programming for kids" book back from the 90s. I find teaching kids in general very hard, much harder than teaching myself because kids don't have the cognitive capacity as an adult.

My parents got me this QBASIC book when I was in elementary school and I remember it being pretty accessible even for very young readers.

https://www.abebooks.com/Absolute-Beginners-Guide-Qbasic-Per...

Also the Usborne series are classics and a lot of them have been made freely available:

https://usborne.com/us/books/computer-and-coding-books

To be honest I just picked moments when the kids were bored and wanted daddy time but weren’t buzzing around the house with excess energy to burn.

It wasn’t something I specifically planned in advance for. Which meant though whole experience was less like homework for them.

As I’m sure you know, sometimes kids just want to experience the stuff their parents do. And when they’re in that kind of mood it’s a lot easier to sit that at a computer than it would be normally.

Well, most of the addressing modes of the Z80 used a 16-bit register pair (i.e. 0 to 64K-1 bytes) to address, the 6502 used a somewhat stranger set of addressing modes, but once again you could address 0 to 64K-1 bytes.
Psst! Let's blow their minds and tell them about the MC68008. (-:
And the 32-bit 4GB limit was often really "just a bit under 2GB" depending on the hardware, OS, etc
3/1 split was common, though. Especially towards the end of 32-bit era.
Not really. 16-bit programs on x86 used 32-bit pointers (effectively 20-bit due to the segment mechanism).

8-bit microprocessors used 16-bit addresses.