I've gone all the way around the circle, I think; early on I started with QBASIC (because it was accessible, and easy), and some rudimentary x86 ASM (because MS-DOS has DEBUG, and I felt a cryptic mystique around using it). Later, I moved on to Java and C, but also learned a few other instruction sets (AVR and Z80). Most recently, I've finally done a complete project, in GCC, incorporating one ASM module (for AVR). So I've learned GAS' particular syntax, avr-gcc's ABI, etc.
I don't recommend x86 for starting out, but it's certainly accessible, and available... ARM too, especially these days. Learning on a classic platform, like recommended above, is probably a good idea. Take some months to learn it, write some algorithms; take a break, come back and do some more. Learn a new instruction set, and so on. Repeat until you're comfortable with how most traditional ISAs work.
I... well, what I'd have to say is, I'd
like to be able to write C in terms of, these statements compile to those instructions, and so on. But there are too many layers of abstraction, with too ineffective optimization, for that to be the case, at least on the last (AVR) project. This is an effective way to approach HDL I think, i.e. that certain combinations of statements (processes) produce certain kinds of registers, gates and so on. But a compiler like GCC at least doesn't quite allow that sort of writing. But I can say, I'm fluent in both formats, and would gladly write that way if I could.
(The danger of that type of writing, is the high level code starts to take on structures that bubble up from the underlying hardware; when porting to different hardware, it may require structural changes to the code itself, if not semantically -- as long as the C code is valid, not abusing edge cases, built-ins and such, it should compile correctly on any platform -- but for best optimization results, this can be a concern.)
Heh... I guess what I'm really trying to say is, not so much anything about an ISA, just a whine about how GCC 9 is so bad on AVR, I can't "write for the platform" even if I try.
The upside to that is -- since I'm not even able to write for the platform (in a usefully optimized way), the code is forced to remain general and should compile, if not
well, then at least
cromulently, for other platforms.
But anyway -- even if you can't "write for the platform" (and, really, you shouldn't
strive for it, exactly because of portability), you can always review the assembled output from the compiler, and see how it's turning statements into instructions, and see which expressions and statements have more overhead than others, etc. It's a good exercise, and being comfortable with the platform's ISA makes debugging so much easier.
Tim