I learned C from KNR, but this is exactly how I began to understand what’s under the hood. On a hard drive somewhere, I have a directory full of C files written to specifically understand how the compiler would translate certain constructs to assembly, both optimised (for speed and size) and unoptimised; then I stepped through them with gdb to understand how stack frames were actually created and used. I can’t think of a better way to really understand what’s going on when you actually run the code.
I started getting a good understand of how the C compiler generates assembler in the early days of the PlayStation 2.
At the end of the project I was working on, before submitting the final disc to Sony, I was fixing bugs where all I had was a stripped ELF file from the disc, a map file, and exception callstack and register contents (a callstack I had to read off of a crummy SDTV!). I’d have to disassemble the ELF, look up the exception call stack addresses and try understand where in the C source code the exception was taking place and how it would have happened.
I learned ASM before C actually, but I admit it probably made C a whole lot easier.