x86 code is the closest you're going to get, without the ability to write
microcode or somehow get further inside the workings of the processor.
x86/amd64 assembly is the closest you can get - but on modern x86
processors, it's pretty far away from the real workings of the chip. On
x86 devices, the hideous x86 instructions are translated into RISC
micro-ops before execution. And while there is plenty of information
about these from Intel and AMD, the details vary wildly between
processor generations and manufacturers, and you can't program at that
level.
I disagree. Doing basic arithmetic in assembler (especially floating point)
can be educational. (But you don't want to do it more than once.)
I'd only bother with the floating point if you are particularly
interested in it. Working at the assembly level gives you an insight
into things like rounding modes, conversions between precisions, etc.
If you want to know about that stuff, then a little assembly is
educational - but most people can use floating point happily while
ignoring these details.
On the other hand, multi-length integer arithmetic in assembly can be
interesting to learn how these things work within the processor.
There're a few other things, but many can also be made available with a
more
carefully designed (than C) higher level language.
Pre-emptive multi-threaded kernels are almost always written in 95%+ C
code. There is always a little bit that has to be in assembly, but it
is usually kept to a minimum (compiler extensions are often used to
reduce the assembly parts - such extensions are, of course, slightly
outside of normal C).
I don't know what is meant by "precisely tracing" garbage collection,
but I know that garbage collection is not something that an OS should
get involved in, except in terms of recovering resources owned by a
process when it dies.
That's what I thought too when it first appeared. Until I examined it more
closely and it was even less orthogonal than x86! (For example, having
two kinds of registers, the Address and Data registers, immediately an
awkward decision needs to be made, if you're generating code, of which
to use. Some things work on D regs and not on A regs, and vice versa. Etc.)
You must have a very strange definition of "orthogonal" to think that
the m68k ISA is less orthogonal than x86. The x86 has about a dozen or
so registers, and all are highly specialised with many operations only
working on particular register combinations. Later versions of the x86
instruction set included instruction varieties and prefixes to allow
more flexibility, but it is as far from "orthogonal" as any large cpu
architecture has ever been.
The m68k, on the other hand, has two sets of main registers - data
registers D0..D7, and address registers A0..A7. To a very large extent,
instructions can choose freely amongst these. Addressing modes are
restricted mainly to using the Ax registers, and many arithmetic and
logic instructions use only the Dx registers - but each can use any of
the Ax or Dx registers (with a very few exceptions). It was far and
away the most orthogonal instruction set until RISC became popular.