Start by implementing in Assembly as little as possible for the programming language as an interpreter.
Meaning just one form of conditionals, just one looping construct, very few basic types, basic IO.
Then use the bare bones interpreter for the second stage, writing a real compiler that is able to process the same basic language and additional constructs.
Another alternative is to add some bytecode format that can then be used equally for interpretation or as input to native code generation.
Niklaus Wirth originally designed P-Code with the intent to make Pascal compilers easier to port. He wasn't thinking to use it as full OS VM, like the guys at UCSD did with they Pascal dialect.
Another trick is to design the bytecode in such a way that it can directly be translated to native code via a macro assembler. It won't generate fast code, but it will provide an easy path for a compiler instead.
Nowadays the Assembly step tends to be replaced by another language that can be found in most platforms, so many tend to choose C.
Not always because it is the best language to write compilers in, but rather because it is ubiquitous or there is some library the authors want to use, thus perpetuating the myth that all languages require C for those not so well versed in compiler design.
It's a sign of maturity to show that a language can bootstrap itself, prolog has been written in prolog, erlang was written with prolog first, then later rewritten in erlang, as other's have pointed out, it's pretty common for C/C++, Lisp, Assembly. This of course applies more to compiled languages.