.assembly hello {} // Declare a "C" like main. .method static public void main() il managed { .entrypoint .maxstack 1 ldstr "IL is cool!" call void [mscorlib]System.Console::WriteLine(class System.String) ret }Maybe the following will excerpt from Anders Hejlsberg will clear up any confusion, the bottom line is that p-code and IL are data structures but their
"I think the approach we've taken with the IL is interesting in that we give you options to control when compilation -- or translation, if you will -- of the IL to native code occurs. With managed C++, you can actually generate native code directly from source. Managed C++ can also generate IL, as can C# and VB. And when you install your code we give you the option to compile it at that point; to compile the IL to native at that point, so that when you run it there's no just-in-time compiler overhead. We also give you the option of running and compiling code dynamically, just-in-time compilation. And, of course, having an IL gives you many advantages, such as the ability to move to different CPU architectures and to introduce verifiability in type safety and then build the security system on top of that." "I think one of the key differences between our IL design and Java byte code specifically, is that we made the decision up-front to <b>not have interpreters</b>. Our code will always run <b>native</b>. So, even when you produce IL, you are <b>never running an interpreter</b>. We even have different styles of JITs. For the compact framework, we have the EconoJIT, as we call it, which is a very simple JIT [Editor's Note: .NET Compact is a subset of the .NET framework designed to be ported to other devices and platforms.]. For the desktop version we have a more full-fledged JIT, and we even have JITs that use the same back end as our C++ compiler. However, those take longer so you would only use them at install time." "When you make the decision up-front to favor execution of native code over interpretation, <b>you are making a decision that strongly influences design of the IL</b>. It changes which instructions are included, what type information is included, and how it is conveyed. If you look at the two ILs, you'll notice that they're quite different. In a sense, our IL is type-neutral. There's no information in the instructions that specifies the type of the arguments. Rather, that is inferred by what's been pushed on the stack. This approach makes the IL more compact. A JIT compiler needs to have that information anyway, so there's no reason to carry it along in the instructions. So you end up with some different design decisions, which in turn makes it easier to translate IL into native code."