Earlier quoted context omitted.
> Hardware access (not exposed by other languages), speed, and possibly executable size are the practical reasons one would write in assembly. This is a bit misleading, accesses to physical memory, disks and to other devices are usually protected by the operating system, not by the language. So you don't have direct hardware access because you program in assembly, but because you run a program without the control of…
>The only thing that you can do with assembly and that you can't really do with higher level language like C is accessing processor specific registers/instruction sets (e.g. SSE). And this is typically done using inline assembly snippets, as there is no reason to write a whole program in assembly when you only need to optimize a single function. The other three most important things you can do in assembly that you ca…
Strictly speaking, yes. I would urge some hesitancy in concluding that is the case, though.
WRT the first, you take some portability penalty for using GNU extensions, but that is probably significantly less than you take by writing in assembly. Unless you're targeting an architecture GCC does not target and your alternative compilers don't have a similar extension, you should still not be writing assembly for this reason alone.
"Directly accessing status flags like the carry flag (necessary for efficiently implementing bignum arithmetic and CPU emulators)"
This falls under both "hardware access" and speed. It certainly is a reason to occasionally break out the inline assembly.
"and optimizing register allocation across complicated control flow (like language interpreters or emulators)"
This is a very bad reason until it actually proves strictly necessary (at which point it falls back under speed and/or size). Modern compilers are quite good at register allocation and getting better, and chip architectures are complicated enough that you're likely to be wrong about what's fastest and/or best. The ability to rapidly try new things will probably get you faster results faster - compare the time taken tweaking optimization flags and rebuilding, versus working out an alternative register allocation and threading it through all the relevant code. Moreover, a small change in requirements can entirely invalidate all of that work. An understanding of assembly and your target architecture sufficient to allow you to allocate registers by hand is still highly valuable when you get into that space, though, so you understand what you're looking for when comparing generated code and benchmark results.