An interesting thought experiment that I've pondered is what I would do if I was given a system that I had to program without even an assembler.
I've programmed on systems where the only access was through direct memory access to the machines memory, and other systems that had a boot loading initiated by a button that started a paper tape reader. I've also used minicomputers that had to have instructions manually keyed in on binary panel switches directly into memory to start a card reader where the cards contained machine instructions to bootstrap the rest of the boot loader off of the remaining cards.
In every case though, somewhere I had an assembler to write the code I needed. What would I do if I didn't even have an assembler? I could write one, but I don't want to do it in machine code. Now days, the easy way would be to simply construct a cross-compiler or cross-assembler that was written in say python on a different machine.
One alternative is to build a hand assembled, really simple macro system. m4[0] or Calvin Mooers' TRAC[1] are possible prototypes, but these flexible macro systems would be difficult to hand compiler into machine code so one might get by with a really basic, more limited macro system. Then each machine instruction could be encoded as a macro and then a primitive assembler could be written as macros.
However, real assemblers do more work, they generally take two passes because they allow symbols to be used instead of literal addresses. So the next step would be to program a real assembler using the primitive assembly language.
After that I suppose a compiler for a simple language like Pascal, basic Lisp, or Per Brinch Hansen's Edison[2] language could be written in assembly language.
Per Brinch Hansen provides the basic directions for construction a very simple operating system from scratch, including the assembler and compiler in the book Programming a Personal Computer[3].
I've programmed on systems where the only access was through direct memory access to the machines memory, and other systems that had a boot loading initiated by a button that started a paper tape reader. I've also used minicomputers that had to have instructions manually keyed in on binary panel switches directly into memory to start a card reader where the cards contained machine instructions to bootstrap the rest of the boot loader off of the remaining cards.
In every case though, somewhere I had an assembler to write the code I needed. What would I do if I didn't even have an assembler? I could write one, but I don't want to do it in machine code. Now days, the easy way would be to simply construct a cross-compiler or cross-assembler that was written in say python on a different machine.
One alternative is to build a hand assembled, really simple macro system. m4[0] or Calvin Mooers' TRAC[1] are possible prototypes, but these flexible macro systems would be difficult to hand compiler into machine code so one might get by with a really basic, more limited macro system. Then each machine instruction could be encoded as a macro and then a primitive assembler could be written as macros.
However, real assemblers do more work, they generally take two passes because they allow symbols to be used instead of literal addresses. So the next step would be to program a real assembler using the primitive assembly language.
After that I suppose a compiler for a simple language like Pascal, basic Lisp, or Per Brinch Hansen's Edison[2] language could be written in assembly language.
Per Brinch Hansen provides the basic directions for construction a very simple operating system from scratch, including the assembler and compiler in the book Programming a Personal Computer[3].
[0] https://www.gnu.org/software/m4/
[1] https://dl.acm.org/citation.cfm?id=365270
[2] http://brinch-hansen.net/papers/1981b.pdf
[3] https://www.amazon.com/Programming-personal-computer-Brinch-...