> I'm referring to writing very large, complex programs
Then the power of good abstractions should be all the more useful!
> that interact directly with hardware
OK if you are using various privileged instructions, writing things with weird calling conventions like interrupt handlers, etc. Then the assembly matters.
But, and this may sound heretical, this stuff is the boundary of the lower level code; its interface with the hardware. For the interior, the precise assembly once again doesn't matter.
> And I say this with many years of experience dealing with other companies badly written device drivers and firmware.
There is a lot of crap low level code out there, yes. And I would say a chief mistake of crap code is not properly respecting layers of abstraction. The low level world needs more http://langsec.org/ where we precisely and mechanistically document the interface, rather than half-assing it with reference implementations.
Just as user space weird instructions get intrinsics exposed to spare the user from writing inline assembly, libraries like https://docs.rs/x86/latest/x86/ should be maintained the device manufacturer or ISA consortium. They should be unit-tested with an emulator too.
We properly do all this legwork to fix the foundation, and the rest of the low-level software will practical write itself, compared to today, and be accessible to a much larger pool of programmers.