Once you get past the stage of manually entering numeric machine code, the most primitive programming tool is a machine code monitor. Intended primarily as a debugging tool, this works with a target program in memory as machine code, and can disassemble small chunks of the code in memory, and typically provides a simple assembler that basically does one instruction at a time, with little or no symbolic capability e.g. no branch target resolution. Perhaps the best-known example is the MS-DOS tool DEBUG.COM.

Past that stage, the next step up is a full-blown symbolic assembler. On 8-bit computers, these were the most commonly used commercial programming tools; I wrote one myself on the Commodore 64, back in the day. They worked the way modern assemblers do: store the source code in a text file, make two passes, or one pass with back patching.

An important limitation of these assemblers was memory. Source code as ASCII text is a rather bulky format; a large program would not fit in memory in this format alongside the assembler and the generated machine code, which meant (unless you could afford to cross develop from a 16-bit machine) waiting a long time for a build to run on floppy disk.

Looking back on that, if I were writing an 8-bit native assembler now, I think I would try a different approach, in between machine code monitor and full classical assembler: keep the program under development, in memory always in binary form (more compact than source text, much more compact than both source and binary), but also keep a comprehensive symbol table so that the IDE could disassemble on the fly into something that would give the illusion that you have source code in front of you. There would be some limits, e.g. each address could be given no more than one name, but it seems to me the memory saving would be well worth it.

So my question is: did any assemblers with the above design, ever exist?