My first experience was with a SHARP PC1500A and a book full of games in BASIC to type and run.
Then wanting to change these games (more lives, more/less difficulty/speed...) I learned how these programs worked and the meaning of each instruction.
Later on a Sinclair ZX81 I followed this practice with another book with games in BASIC. Then an book on assembly for the ZX where you did have an example of assembly code equivalent for each BASIC instruction and an explanation for all the Z80 op-codes. From this I started learn assembly.
With the help of a reference book describing the hardware of the ZX and lot of magazines articles, I started to add memory (2K, 16K, then 128K with a 8K window like EMS for the PC), mechanical keyboard, sound generator, eeprom memory to store code/data between reset/shutdown, logical and analogical I/O, speech synthesizer...
Years later I received a PC (TANDY 1000 EX) with GW-BASIC, followed by a copy of TURBO PASCAL with its incredible online help and the SWAG archive. With the help of the reference 8086 documentation I began to learn x86 assembly to boost my pascal programs.
VISUAL BASIC let me create windows easily, but was quickly replaced by BORLAND PASCAL.
Way more later, at school, I learned C on a HP 9000, Fortran on HP 1000/RTE, 68000 assembly on a development board, IBM S/360 assembly on a VM of a S/390, SmallTalk, Prolog, Lisp (CLISP) and Smeci.