Nowadays we’re very, very far from the hardware - hardware that has grown very complicated in comparison.
If that isn't dark magic I don't know what is.
Curiously, I found learning Rust way more challenging than learning 16-bit assembly (it was way simpler back then; no complex instructions, less baggage, simpler processors... and less expectations :)).
For x86, at least, I wouldn't even say that it was less complex. Segmented memory alone is a huge complication, and then on top of that there was all the legacy CISC stuff like the BCD helpers or ENTER/LEAVE; x64 is comparatively streamlined.
For those who want to re-live the moment, look at this PDF starting on internal page 873 (file page 894): http://vtda.org/books/Computing/OperatingSystems/DOSPowerToo...
At least with DEBUG and assembler I could reasonably reason and do things by hand. With many modern languages I have no idea where to even start checking what they do and how.