CHAPTER 18 UNDERSTANDING CIL AND THE ROLE OF DYNAMIC ASSEMBLIES
To compile your updated HelloProgram.il file into a new .NET *.exe, you can issue the following
command within a Developer Command prompt:
ilasm /exe HelloProgram.il /output=NewAssembly.exe
Assuming things have worked successfully, you will see the report shown here:
Microsoft (R) .NET Framework IL Assembler. Version 4.0.21006.1
Copyright (c) Microsoft Corporation. All rights reserved.
Assembling 'HelloProgram.il' to EXE --> 'NewAssembly.exe'
Source file is UTF-8
Assembled method Program::Main
Assembled method Program::.ctor
Creating PE file
Emitting classes:
Class 1:
Program
Emitting fields and methods:
Global
Class 1 Methods: 2;
Emitting events and properties:
Global
Class 1
Writing PE file
Operation completed successfully
At this point, you can run your new application. Sure enough, rather than showing a message within
the console window, you will now see a message box displaying your message. While the output of this
simple example is not all that spectacular, it does illustrate one practical use of programming in CIL
round-tripping.
The Role of peverify.exe
When you are building or modifying assemblies using CIL code, it is always advisable to verify that the
compiled binary image is a well-formed .NET image using the peverify.exe command-line tool, like so:
peverify NewAssembly.exe
This tool will examine all opcodes within the specified assembly for valid CIL code. For example, in
terms of CIL code, the evaluation stack must always be empty before exiting a function. If you forget to
pop off any remaining values, the ilasm.exe compiler will still generate a compiled assembly (given that
compilers are concerned only with syntax). peverify.exe, on the other hand, is concerned with
semantics. If you did forget to clear the stack before exiting a given function, peverify.exe will let you
know before you try running your code base.
662