My understanding is that a compiler converts the high level language into machine code. I have a question as to whether a compiler(say VC++) in-turn uses an assembler too? I remember seeing assembly code, whenever there is a crash or something like that.
A compiler goes directly to machine code.
The debugger will show the machine code instructions as assembler, but the debugger can also show other code which wasn't compiled by the compiler.
The compiler may also include an assembler so you can include inline assembler code in with the higher level language or generate assembler output.
It depends on the compiler; many compilers can compile to assembly. For instance, if you pass the '-S' flag to gcc, like:
gcc -S -o test.S test.c
That will output assembly for your test.c file into the file test.S which you can look at. (I recommend using -O0 if you're gonna be trying to read the assembly, because compiler optimizations in there will likely confuse the heck out of you).
Since you mentioned Visual C++ in your question, Paul Dixon points out below that Visual C++ uses the /FA flag to accomplish the same thing.
Most compilers will have an option to view an assembly listing
- VC can be told to output an assembler listing with /FA
- with gcc, use the -S switch
A compiler translates some high level programming language to some lower level language (as machine code, assembly or even another high level language, for example from Vala to C, or from uC++ to C++).
I don't know about VC++, but most compilers, as GNU GCC doensn't include an Assembler, but invoke an external Assembler program (as NASM, or GNU AS).
Cheers
In general, a compiler translates one language into another. Most compilers target machine code; here are the most common ways of doing this, in order from lowest-level to highest-level:
- Produce machine code directly, by including back-ends for each instruction set.
- Produce assembly language, which is passed to an external assembler. This is what gcc does. After all, why not use existing assemblers? Generating opcodes directly is a pain.
- Generate a low-level intermediate form of the code, such as LLVM bytecode, which gets transformed into machine code. LLVM is a godsend for compiler-writers, because it handles a vast number of optimizations and supports a lot of back-ends, while letting you write at a higher level than assembly.
- Transform the code into a language like C, and then pass it to another compiler. Facebook does this to PHP: they compile it to C++, and then use gcc to compile that to assembly, which is assembled to native code by GNU as.
If you'd like to try writing a compiler, I'd recommend starting off with something like C as the back-end. If you'd like to get more elaborate later, try LLVM. If you try to produce assembly language or machine code directly, it'll probably be less efficient than what a C compiler or LLVM would produce. I speak from embarrassing personal experience on this one.