Bare metal Updated +Created
Bare metal programming is to run a program without an operating system below it.
Or in other words, it is basically implementing an operating system/firmware yourself ad hoc, together with your actual program.
How computers work? Updated +Created
A computer is a highly layered system, and so you have to decide which layers you are the most interested in studying.
Although the layer are somewhat independent, they also sometimes interact, and when that happens it usually hurts your brain. E.g., if compilers were perfect, no one optimizing software would have to know anything about microarchitecture. But if you want to go hardcore enough, you might have to learn some lower layer.
It must also be said that like in any industry, certain layers are hidden in commercial secrecy mysteries making it harder to actually learn them. In computing, the lower level you go, the more closed source things tend to become.
But as you climb down into the abyss of low level hardcoreness, don't forget that making usefulness is more important than being hardcore: Figure 1. "xkcd 378: Real Programmers".
First, the most important thing you should know about this subject: cirosantilli.com/linux-kernel-module-cheat/should-you-waste-your-life-with-systems-programming
Here's a summary from low-level to high-level:
Figure 1.
xkcd 378: Real Programmers
. Source.
Video 1.
How low can you go video by Ciro Santilli (2017)
Source. In this infamous video Ciro has summarized the computer hierarchy.
Programming language Updated +Created
A language that allows you to talk to and command a computer.
There is only space for two languages at most in the world: the compiled one, and the interpreted one.
For 2020 now, when you have a choice, you must go for:
  • Python as the interpreted one
  • C++ for compiled
Those two are languages not by any means perfect from a language design point of view, and there are likely already better alternatives, they are only chosen due to a pragmatic tradeoff between ecosystem and familiarity.
Ciro predicts that Python will become like Fortran in the future: a legacy hated by most who have moved to JavaScript long ago (which is slightly inferior, but too similar, and with too much web dominance to be replaced), but with too much dominance in certain applications like machine learning to be worth replacing, like Fortran dominates certain HPC applications. We'll see. Maybe non performance critical scripting languages are easier to replace.
C++ however is decent, and is evolving in very good directions in the 2010's, and will remain relevant in the foreseeable future.
Bash can also be used when you're lazy. But if the project goes on, you will sooner or later regret that choice.
The language syntax in itself does not matter. All that matters is how many useful libraries and tooling it has.
This is how other languages compare:
  • C: but cannot make a large codebase DRY without insanity
  • Ruby: the exact same as Python, and only strong in one domain: web development, while Python rules everything else, and is not bad on web either. So just kill Ruby, please.
  • JavaScript: it is totally fine if Node.js destroys Python and becomes the ONE scripting language to rule them all since Python and JavaScript are almost equally crappy (although JavaScript is a bit more of course).
    One thing must be said tough: someobject.not_defined_property silently returning undefined rather than blowing up is bullshit.
  • Go: likely a good replacement for Python. If the ecosystem gets there, will gladly use it more.
  • Java: good language, but has an ugly enterprisey ecosystem, Oracle has made/kept the development process too closed, and API patenting madness on Android just kills if off completely
  • Haskell: many have tried to learn some functional stuff, but too hard. Sounds really cool though.
  • Rust: sounds cool, you will gladly replace C and C++ with it if the ecosystem ramps up.
  • C: Microsoft is evil
  • Tcl, Perl: Python killed them way back and is less insane
  • R, GNU Octave and any other "numerical computing language": all of this is a waste of society's time as explained at: Section "Numerical computing language"
  • Swift: Ciro would rather stay away from Apple dominated projects if possible since they sell a closed source operating system
The lower level you go into a computer, the harder it is to observe things Updated +Created
This is a general principle of software/hardware design that Ciro feels holds wide applicability.
The most extreme case of this is of course the integrated circuit itself, in which it is essentially impossible (?) to observe the specific value of some indidual wire at some point.
Somewhat on the other extreme, we have high level programming languages running on top of an operating system: at this point, you can just GDB step debug your program, print the value of any variable/memory location, and fully understand anything that you want. Provided that you manage to easily reach that point of interest.
And for anything in between we have various intermediate levels of complication. The most notable perhaps being developing the operating system itself. At this level, you can't so easily step debug (although techniques do exist). For early boot or bootloaders for example, you might want to use JTAG for example on real hardware.
In parallel to this, there is also another very important pair of closely linked tradeoffs:
  • the lower level at which something is implemented, the faster it runs
  • emulation gives you observability back, at the cost of slower runtime
Emulation also has another potential downside: unless you are very careful at implementing things correctly, your model might not be representative of the real thing. Also, there may be important tradeoffs between how much the model looks like the real thing, and how fast it runs. For example, QEMU's use of binary translation allows it to run orders of magnitude faster than gem5. However, you are unable to make any predictions about system performance with QEMU, since you are not modelling key elements like the cache or CPU pipeline.
Instrumentation is another technique that has can be considered to achieve greater observability.
User mode emulation Updated +Created
User mode emulation refers to the ability of certain emulators to emulate userland code running on top of a specific operating system, usually Linux.
For example, QEMU allows you to run a variety of userland ELF programs directly on it, without an underlying Linux kernel running.
User mode emulation is achieved by implementing System calls and special filesystems such as /dev manually on the emulator one by one.
The general tradeoff is that simulation is less acurate as it may lack certain highly advanced kernel functionality you haven't implemented yet. But it is much easier to run executables with it, and you don't have to wait for boot to finish before running, you just run executables directly from the command line.
Sample code Updated +Created
Like everything else in programming, the only way to really understand this is to play with minimal examples.
What makes this a "hard" subject is that the minimal example is large because you need to make your own small OS.