Talking about generating code for a generic compiler is pretty much the same regardless of the language, once you get down to it. The complexities of the different language involve efficiently handling the semantics of the environments in the language (i.e. Scheme has things like closures and continuations, whereas something like BASIC does not).
But once you've decided how things like that are represented (and some affect efficiency in terms of memory layout, accessibility, etc.), the code generation is straightforward.
The distinctions that you're encountering are the differences between, say, a Scheme compiler that compiles to C and then hands that off to a C compiler (who may compile it to assembly and hand it off to an assembler), vs generating machine instructions directly in RAM by your compiler.
The different phases give you an opportunity to add optimizations, and offer a separation of concerns. Generating C code can be easier than generating assembly or, especially, machine code, because the C compiler can do some heavy lifting for you (such as architecture portability).
But several systems can use C to compile code that in immediately loaded via the dynamic linking process and executed.
Compiling to an intermediate language (ala JVM, CLR) can simplify things as well, and then you JIT that. Compiling JVM bytecodes is not particularly difficult, as it's a simple stack machine. OPTIMIZING that code is a different problem, but converting in to machine code is pretty straightforward. CLR is different because it captures more of the semantics of the code being compiled. CLR is more like an intermediate phase of compilation, in contrast to the JVM which is actual code designed to be executed as is.
In the end, it's all arrays of data in RAM somewhere, whether that data is machine code or VM code is a matter of detail. Whether that array is in RAM proper or mapped in by the VM from a file is another detail. With virtual memory, you system probably doesn't care one way or another.
So it boils down to focusing on the code generation proper. Once you're comfortable with that, directing it to other compilers, to RAM, or to files is a minor step.