I saw my first computer in 1978. It was a Tandy TRS-80, and it was running what today we'd call a slide show. It was, however, entirely in text and very, very simple graphics.
It had 16KB of RAM, and permanent storage was sound on a fairly standard external cassette tape drive. I can still draw the waveform of a bit, and the start/stop patterns. You could program it in a simple BASIC that had limited variables, and no subroutine parameters.
No parameters in subroutines!
But I was hooked. I wrote two BASIC programs, then ran out of patience. It had to run faster! A 1.77 MHz Z80 running interpreted BASIC wasn't fast enough.
So I smashed the stack. I won't go into the details, but I bootstrapped into assembler (the BASIC did have PEEK and POKE) and wrote a compiler. The BASIC version, two copies of the machine code version, and the variables, all fitted into the 16KB memory. Two copies because it wasn't relocatable, so I compiled to copy 1, used that to compile to copy 2, then machine-code saved copy 2 to cassette.
It was cool writing different variants of sort, then sorting the data that was in the memory mapped screen. You could see the heavier items fall to the bottom in quicksort, or migrate one at a time to the top in a bubble sort. It was pretty raw, and enormous fun.
Why do I tell you this?
Today at work I took a subroutine that was taking 171ms per call and making the GUI run as slow as a snail on valium, and re-wrote it to take less than 10ms per call. The methods I used were straight out of the techniques I learned in that first 3 months of machine code programming (not assembler -machine code), and my colleagues couldn't really understand it.
There followed an impromtu "training session" in which I explained how CPU cores work, how machine code can be mapped to them, how assembly code matches machine code, and the way the instructions actually match the hardware, in some sense.
A lot of what I talked about is now outdated, it is, after all, 30 years old. But the techniques are still applicable on occasion. They were amazed that they didn't know this stuff, and intrigued as to how I do.
It's just what I grew up with.
Should programmers in C++, Haskell, Lisp, Python, etc, know these things? Or are they really mostly irrelevant, becoming more so, and soon to be known only by true specialists and dinosaurs like me?
As for the why of it:
No other programming language will give you the feeling that it is you that controls the computer as good as assembly ever will, other than the lucky few that get to program microcode.
Assembler is what it all eventually boils down to, it gives you a first hand view at the von Neumann bottleneck and how small the letterbox is through which the CPU views the memory.
After you get a good long hard look at that your programs will never be the same.