Tuesday, October 18, 2005

Insights on x64 v. x86

In my last post, it was certainly clear that I needed to do some lernin'. A very helpful fellow at MS pointed me to the following blog entries:

http://blogs.msdn.com/joshwil/archive/2004/10/15/243019.aspx
http://blogs.msdn.com/joshwil/archive/2005/05/06/415191.aspx
http://blogs.msdn.com/joshwil/archive/2005/04/08/406567.aspx

First, it is worthwhile to read the related articles referenced in the 10/15 post. You should also realize that during these posts, the handling of x64 targeted assemblies was in flux, and later articles contradict the earlier ones. However, the overall picture is more clear when you read them all.

The one thing I was right about in my last post was that basically these issues do arise from the program saying "I am not going to run in this environment". Whether or not they *could* run is a decision the developer has made, and is trying to enforce. In the .net world this safety mainly revolves around the use of Interop, PInvoke, and unsafe code blocks.

Version 1.1 of the framework (and strangely v. 2.0 of CLR Header- 2.0 framework produces v2.5 headers) did not have a concept of targeting processor architectures - this targeting is done in the assembly manifest. That basically means all 1.1 assemblies are agnostic. I ran a few simple tests, and here is what I found:

1. The main problem I was having when I wrote my last post was because I am an idiot, and was getting a Bad Image Format Exception (BIFE) because I was trying to load a 2.0 assembly into a 1.1 executable. Don't try that, and don't try to debug x64 issues when it happens.

2. The tool called corflags is a great help mainly as a quick assembly header reader (use it with assembly name only and it will display the target info - both 2.0 and 1.1).

3. When a 1.1 executable is loaded on an x64 machine it is run in the WOW64 as a 32-bit process and utilizes the 32-bit framework.

4. When a 2.0 executable is loaded, it runs according to how the configuration targets the architecture. If this 2.0 executable is loaded and references a 1.1 assembly, there is no problem on load. However, if the 1.1 assembly utilizes PInvoke, Interop, or unsafe code there could be runtime problems. For this reason, you should probably target x86 when compiling a 2.0 executable that utilizes these operations, or if you don't know what it does.

5. If you compile your application to "Any CPU" and the assemblies you use specifically target x86, you will BIFE it at load time. You can do two things here - compile yours to target x86 and forgo the wonder of 64-bit computing, or force a header change with corflags. The second option just seemed to break things for me.
Submit this story to DotNetKicks

No comments: