Putting the “You” in CPU
cpu.land
cpu.land
Thanks for reading and thanks for all the corrections, in glorious Hacker News fashion. It's definitely a pleasant surprise to see my project here. Putting the "You" in CPU is still very much a work in progress — I was hoping to polish it a lot more and even add some more content before posting on HN later next week :)
Some backstory on me: I'm 17 and left high school a year ago to work full-time at Hack Club (https://hackclub.com/). I've been programming for as long as I can remember, and started homeschooling about 6 years ago to focus more on that (and my other interests).
Since I'm entirely self-taught, I haven't taken any college systems classes — and while I had picked up a lot, I wasn't happy with my answer to "what happens when you run a thing." So I let myself spend a shit ton of time actually learning as much as possible. What I found was that:
1. Operating systems and hardware are really fun to learn about!
2. Wow, online resources on this stuff are terrible.
A decent portion of my research ended up at PDFs of lecture slides from 2014, or StackOverflow answers that were, in fact, incorrect or vastly oversimplified.
So, I wrote Putting the "You" in CPU to hopefully provide a better resource to people who wanted to start teaching themselves all this stuff! While I don't provide perfect coverage (still need to write a couple paragraphs on SMP), it's a lot better than most of what I've seen. I also had fun drawing and making diagrams for the first time, I think I definitely got progressively better and I'm really proud of some of the drawings in the latter few chapters.
P.S. The whole thing is open source on GitHub if you want to look under the hood: https://github.com/hackclub/putting-the-you-in-cpu
I've been thinking this a lot lately, searching for things like: a detailed block diagram of the Linux kernel, how page tables work, a comparison of function call ABIs on different platforms, details about low-level network protocols, reserved Linux PID numbers, etc.
Occasionally I would find a Reddit thread with an answer, but it was mixed in with the usual Reddit dross, and I doubt that Reddit is a reliable place to store knowledge. StackOverflow was particularly unhelpful, as the questions are mostly oriented around accomplishing particular tasks, and the answers are necessarily brief.
Nowadays, for general knowledge, I skip Google's enshittified search and go straight to Wikipedia, but Wikipedia has limits on how much detail it will go into about technical topics.
I wonder if there's a need for a comprehensive wiki for all the details of computer guts? There are lots of scattered resources, but having them all compiled in one place would be awesome.
Another thought: a focus on staying up to date would be important. A lot of information about system internals I find is actually historical, and while that's useful sometimes, it's still a pretty big gap. Modern systems are quite poorly documented.
https://wiki.osdev.org/Expanded_Main_Page is quite good or at least a starting place. It's very x86-centric, though, and doesn't have a lot of coverage. Also, a decent portion is out of date. I used it a decent amount as at least a component of my research for You in CPU.
Agree that modern systems are even more terribly documented than systems in general. So many of the resources I found, even recent ones, were referring to stuff from the original x86 that had long changed. Almost everything I found about ELF or memory layout assumed the memory space was 4 GiB.
Finally, I hope Putting the "You" in CPU gets well-SEOed if only so people like me Googling for modern answers to these questions will find at least something. I tried to make everything as relevant to modern day tech as possible, and to link to up-to-date resources.
Hate to say it, but you’re probably very right.
That's on me, I'm a fan of your work and saw this pop up on my GitHub feed. I probably should have considered if you were ready for it to be shared. I hope the attention was mostly positive!
glad you like it :3
Have you actually gone down already the rabbit hole that is the history of computing and alternative approaches to what we have today?
Again, I recognize this makes things simpler, not more difficult, for the hardware, and even a compiler’s emitter will spend very little code dealing with it. But it’s not easy on the eyes.
At least if you didn't skip the computer architecture and operating systems classes.
For me it was a common thing to define an ISA, implement a simulator and assembler, and hand-write some assembly as part of learning how computers work. A dedicated man might go the extra mile and implement it in FPGA, or write a LLVM backend.
Then there is all the operating system aspect. It's quite common to implement your own kernel there to learn, or at least to modify an existing one.
I don't say that you need to be an expert on low level programming to write good code (sometimes this is even a hindrance as quite some of these people are prone to the premature optimization anti-pattern) but one should imho know at least the basics and have a high level overview of the low level stuff.
But frankly the reality is that even people who struggle with mere syntax, people who have no clue whatsoever what's going actually on, "contribute" code way to often to the corpus that you need to deal with in professional settings.
</rant>
Edith thinks I should at least praise the great article we're commenting on here!
Very nice write up.
The only thing that I miss a little bit is a kind of "disclaimer" that what gets presented is "just" the result of a market race, and not how computers need necessary to work like. Not going into the details of possible hardware architectures and implementation, but even on the "user facing" level (the operating system and application layer) things can look very, very differently. Just as an example: https://en.wikipedia.org/wiki/Genera_(operating_system)
At my university, most of the classes the GP is talking about (logic design, microprocessor implementation, OS-level programming) were in the Electrical Engineering curriculum. The lowest level that the CS curriculum got to was writing a parser for a programming language.
As time goes by the topics to focus also changes (should we have Machine Learning courses now?), so that’s to be expected.
If you're gonna skip education, you better make up for it by going above and beyond what they teach with your self-learning.
There's a reason abstraction layers exist, perhaps you should try and figure out why your mental model of software does not account for that.
Much like a house is more than just the structure itself, so is the realm of computers.
From my experience a substantial fraction of programmers learn the absolute minimum to get a job.
Then they either learn on the job or ask the same questions over and over again, never learning. The latter being the really annoying people to work with.
If you can write programs, then you're a programmer. That's it.
There is never a strong focus on x86, and any kind of rote memorization has nothing to do in a higher education institution.
Myself I don't understand how one could write any code without understanding how the code gets run.
I think this perhaps says more about you then it does the people to whom you're referring. If you can't understand how someone can write code to perform tasks and extrapolate from that ways that programming can be used to perform tasks, without any underlying knowledge of the architecture that it runs on, then I would suggest your education is currently incomplete.
How far down does the full stack go? Hardware? Digital electronics? Analogue electronics? Physics? Further?
Code is typically used to run a service running for a potentially long time leveraging hardware resources which are made accessible and shared with other processes through an operating system.
To ensure that the service runs well and doesn't hamper other services sharing those resources, you need at least high-level understanding of how the hardware and operating systems work.
Depending on your definition of “service” here, I’d argue that most code is not written to run services, and certainly not long-running services. Like, core-utils is a shitton of programs, and a shitton of code, and none of that runs as a service. Most of what you mentioned in your first comment aren’t services.
Bio researchers don’t write long-running services. They don’t even really understand how computers are allocating resources. They don’t know shit about putting an HPC cluster together and managing it. Are they not writing code?
I agree with the other person who said your education seems incomplete. Yours is a very narrow view of computers and computing.
You may want to know why they are the size that they are, be able to extract meta-information, configure how the dynamic linker works, extract debug info, etc.
Some of things are actually critical for installation or deployment.
I've got bad news if you work anywhere that is web or web adjacent then :)
Are you referring to a curriculum of specific university which makes students do both mentioned things?
So I guess you are avoiding answering my question: can you give an example of university's curriculum, when they make students work on both FPGA and LLVM? Because that's what you were suggesting in your statement.
The school I went to definitely did the FPGA bit as there was a research team looking into FPUs at the time. I don't think we did any LLVM, though one of the teaching assistants I was friends with was excited about it as he was specifically researching SSA transformations, but most of my exposure to that must have been outside of class.
That school specializes in theoretical computer science so I wouldn't really recommend it to anyone willing to do practical things, nor can I vouch for the quality of any remaining practical bits today.
In practice I don't really know where to get a good computer science education. It seems computer architecture has become optional in quite a few top-ranking institutions as well. And they tend to follow trends like the whole AI fad. Your best bet is to research what kind of research the associated people do.
I'm sorry that you wasted your money on an educational investment that doesn't pay dividends.
Which part of the grandparent's post led you to the conclusion that his/her education wasn’t good?
Don't assume everyone had the same uni experience.
Fixed the code example and merged!
> The first byte (05) is an opcode specifically representing adding the EAX register to a 16-bit number. The remaining bytes are 512 (0x200) in little-endian byte order.
That explains only the first 3 of the 5 bytes in the instruction. What are the remaining 00s for? Did he perhaps mean that the opcode is for adding EAX to a 32-bit number?
From [0]:
> Since shebangs are handled by the kernel, and pull from buf instead of loading the whole file, they’re always truncated to the length of buf. Apparently, 4 years ago, someone got annoyed by the kernel truncating their >128-character paths, and their solution was to double the truncation point by doubling the buffer size! Today, on your very own Linux machine, if you have a shebang line more than 256 characters long, everything past 256 characters will be completely lost.
What is the reason for silently truncating someone's filepath? The kernel, of all places, should not be doing such things. Granted, 256-byte long file paths don't make sense, but 256-byte long path+argument strings will almost certainly happen sometimes. To just silently break someone's script is wrong.
A couple years ago someone attempted a patch to the kernel that would at least fail loudly in the case of oversized shebangs. This ended up causing problems for NixOS which, being Nix, already was using oversized shebangs with lots of long nix-store paths. They were previously being silently truncated but still working, and suddenly all those scripts failing caused a lapse in backwards compatibility! So the patch had to be undone and we haven't gotten anything similar since.
See https://lwn.net/Articles/779997/ for more info.
it's there to tell where the interpreter for the current file is.
shebang can't even handle more than a single argument on its own. if you have `#!/bin/program -args somescript`, it will divide it into ['/bin/program','-args somescript'], which is almost never what you actually wanted. ( this is linux specific, shebangs aren't necessarily universally portable between all unices )
if you want to do something complex, make it `#!/bin/sh` and then `exec` from the current file with whatever arguments you need.
one thing that link doesn't mention is that you can use env to lookup an interpreter via the current path.
`#!/usr/bin/env python3` for example, will find whatever `python3` the users is using, without having to know where it is.
this can be useful for scripts that you will be running from virtual environments, for example, which work by overriding the PATH to the python interpreter.
you wouldn't want to do this with anything installed, however, since you wouldn't want installed programs to let the user control what interpreter to use. instead, you should just use an absolute path.
there is an option in env, -S, that can be used to parse a command line from a single string specifically to handle this limitation.
after years of avoiding much trickery in shebang lines, it seems like a questionable practice at best.
shebang processing is the kernel peeking at the first couple hundred bytes of a file to see if it should execute it using some other file instead of running it directly. there isn't a userspace yet because it's still setting the process up. even if there was a userspace, PATH searching should be done for the `exec`ing process' path, not the PATH given to the new process. so you'd have to squirrel away the calling processes path somewhere on top of everything else.
so, it would be a pain. and also incompatible with all of the previous exec system calls, since if you "fixed" it to follow the path, anything not expecting that could break.
Clearly this is targets only people with multiple PhDs in electrical engineering and computer science.
How do you get it all on one page? That gives you the ability to ctrl+f stuff, skip past things you know by skimming their contents, scroll back up to things you need to re-read, and way more.
What does this mean?
If you could enable opening of the graphics such as the one illustrating the hierarchical page table concept to their original high resolution, that would be nice for readability.
Very considerate!
- Computer architecture or CPU design book covering modern designs with their tradeoffs
https://www.amazon.com/Computer-Architecture-Quantitative-Ap...
- Introduction to Verilog or VHDL (languages for hardware) maybe on FPGA's or well-known boards
https://www.amazon.com/Programming-FPGAs-Getting-Started-Ver...
- High Speed Digital Design (many recommended it)
https://www.amazon.com/High-Speed-Digital-Design-Handbook/dp...
- Cookbook with many examples for FPGA's
I don't have one. Most with these titles are expensive. One that looked promising had bad reviews. I'll leave it to HN to fill in the blanks.
- High-level synthesis
Most exciting one I remember when I stopped researching this stuff was Synflow. I don't know if they're still around.
Before that, I had saved Baranov's work which showed how to turn Abstract, State Machines into actual hardware. It was like a how-to on high-level synthesis that he used commercially at Synthezza. I still share them periodically in case someone wants to build an OSS version. I also saw ASM's used in verifying compilers and hardware in separate work. There's a good chance someone can turn many things into a unified, field theory of sorts using ASM's.
https://www.amazon.com/Finite-State-Machines-Algorithmic-Com...
https://www.linkedin.com/pulse/second-ebook-samary-baranov-h...