Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why .net assemblies differ for different architectures?

Tags:

.net

x86

64-bit

I can build my C# project for x86 and for x64. Why? I thought it generates a special code which is not platform specific at all.

like image 827
Valentin Golev Avatar asked Feb 20 '10 10:02

Valentin Golev


4 Answers

First, let me be blunt and say that I don't know the whole story here, I'm going to answer with what I think I know. I'll happily delete or change my answer if someone can tell me where I'm wrong.

The way I understand it, this setting is a flag that says "the assembly is supposed to be run in this type of architecture". That's for the x86 and x64 setting. The MSIL/.NET setting is just saying "I don't care, I can run on either, so pick the one that is optimal or available."

For instance, you might be making calls to Win32 API functions through P/Invoke, in which case the assembly won't work on x64 and you should flag it as x86.

So if my understanding is correct, here's how the three flags make the assembly run (note, it's the main assembly, the program assembly, that dictates this, not each individual assembly for themselves) on different platforms:

Setting        x86      x64  <-- Platform (CPU/OS)
MSIL/.NET     32-bit   64-bit
x86           32-bit   32-bit
x64           N/A (*)  64-bit

The N/A for x64 assembly on x86 means that the assembly won't load, and you'll get an exception if you try.

Also note that conflicting settings involving x86 and x64 will make your program crash at one point or another. If the main assembly is set to x86, it will run as a 32-bit process on both a 32-bit and 64-bit operating system, and any attempts at loading assemblies flagged as x64 will fail. Likewise, if the main assembly is set to x64, it will only run on 64-bit operating system, and any attempt at loading an assembly set to x86 will fail.

A MSIL main executable assembly will run as 32-bit on a 32-bit operating system (like if it was set to x86, with the above failure point,) and as 64-bit on a 64-bit operating system (like if it was set to x64, with the above failure point.)

Obviously Typically, you want to go with the MSIL setting if you're not calling assemblies that are flagged as something specific, and as long as you're not doing P/Invoke that isn't portable across 32-bit and 64-bit (I have no idea if this works, if P/Invoke to win-api functions will map to a correctly bitsized dll or not.)

Since references are pointers, and pointers are stored as a native x-bit address on the two platforms, depending on the amount of references you have, you might have a case against just going with MSIL. You should, however, verify that this is a problem before you make a change to your settings.

like image 148
Lasse V. Karlsen Avatar answered Nov 07 '22 13:11

Lasse V. Karlsen


That flag is important for EXE files. It decides if you run in a 32 or 64 bit process. If you use "native" DLLs from your .NET code you need follow the architecture for those DLLs.

The "Any CPU" on EXE files will choose x64 if available.

like image 37
Arve Avatar answered Nov 07 '22 14:11

Arve


First off, setting Platform Target to x86 on your .exe project is a very useful when you are debugging your project on a 64-bit version of Windows. The VS2005/8 debugger doesn't support Edit + Continue on 64-bit code.

Choosing x86 in your release build is something you should do if you program has a dependency on a component that only works in 32-bit code. That's not uncommon, there are tons of COM components out there that never have and never will be ported to 64-bit unmanaged code. One classic example is the Microsoft Jet database engine.

Choosing x64 is very unusual, there isn't much unmanaged code that is only available in the 64-bit version. Notable is that you'll get warnings when you build your assembly, there are several .NET framework assemblies that contain unmanaged code; only the 32-bit versions of them are available in c:\windows\microsoft.net. You can safely ignore those warnings, the 64-bit versions are actually installed in the GAC.

One wrinkle when selecting x64 is that the C# 3.0 compiler will emit a binary that asks Windows to create the startup thread with a 4 megabyte stack size, instead of the default 1 megabyte. That's somewhat justified, 64-bit code does need more stack to store pointers and return addresses.

Finally, the Windows SDK has the Corflags.exe tool available to switch the bit-ness of an assembly after it is built. The /32BIT+ option is equivalent to setting Platform Target to x86. Using /32BIT- ensures that the assembly will run in 64-bit mode on a 64-bit operating system. Changing the default stack size is possible with the Editbin.exe tool.

like image 3
Hans Passant Avatar answered Nov 07 '22 13:11

Hans Passant


I believe that the reason why there are different targets is due to the size of scalar types. I think it also affects the way in which COM objects are handled.

I have a situation where I have a 3rd party .NET library which if used within a 64-bit application the program fails when calling into the library, thus I have to restrict to 32-bit only mode.

like image 1
Brett Ryan Avatar answered Nov 07 '22 12:11

Brett Ryan