I hope my readers will indulge me while a take a quick detour into one of my favorite things; Programmable calculators.
As a gentle prologue to machine language programming I don't think you can do better than one of the old programmable calculators. In my youth the very first thing I learned to program was my father's HP-67 calculator. I still have one today. Me and my brother Ernie both had TI-57 calculators and we had a good time with these, trying to cram something interesting into 49 steps of program memory. ;-)
My personal HP-67.
If you look at the Commodore MOS KIM-1 it sort of looks like a giant calculator.
The HP-67 is a small computer, and like the KIM-1 it even has its own permanent program storage in a form of a magnetic card reader. It has it's own language that resembles assembly language, but it is like an assembly language with training wheels.
Like the assembly language coder, the HP-67 programmer needs to deal with registers, with conserving space, with storing and retrieving values. Many ideas are represented. There is even a way to jump indirectly using a value in a register.
Here is some 6502 assembly code:
For comparison here is some HP-67 code.
The user is insulated from certain kinds of problems such as programs accidentally overwriting themselves because the programs can only change values in the registers. So there is program memory (224 instructions) and there is data memory (26 registers).
The programmer is also introduced to LIFO stack concepts.
The quality of documentation that came with these calculators put programming within the reach of most people.