The step with declaring hw registers in assembly reminds me how assignment of value to pointer is IIRC at best implementation defined, and at worst UB, and playing around with volatile saves you not from zealous optimizer.

Arguably every hardware register should be declared that way as a symbol

That was a common feature on Borland and Microsoft compilers for MS-DOS.

I mean, at its most basic, it's a feature from even the earliest compilers for C.

Not sure if Borland or MS shipped big fat symbol tables for all hardware registers of an IBM PC though?