How can we use masm32 to distinguish between 32-bit OS and 64-bit OS?
Posted on 2006-06-19 00:49:23 by jeffery
In what manner?

You can use CPUID instructions and/or API calls to determine the machine type. Native 32-bit programs can run in Long Mode (ideally)... so you couldn't really discern the difference AFAIK.

Trying to hardcode some instruction (inserting the 64-bit opcode into the program manually), that is expected to reproducibly return a specific value might crash the program as well (#UD/GPF/Double Fault).
Posted on 2006-06-19 01:03:44 by SpooK
Has any masm32 API can invoke to distinguish?
Posted on 2006-06-19 01:27:55 by jeffery
MASM32 is nothing special. The actual m32.lib is just a bunch of non-standard code slapped together. MASM32 in its entirety has libs/incs to utilize the Win32API. Just look up any function on MSDN, and you should generally be able to use that appropriate function with MASM32.
Posted on 2006-06-19 02:47:32 by SpooK
This looks like a really good candidate for the 'seh trapping on illegal opcode' technique described here not long ago..
You could write an exception handler designed to catch the fault generated by attempting to execute some carefully-chosen 64bit opcode on a 32bit machine.. if the opcode works, great, we're 64bit.. if it fails, the seh traps the fault, great, we're 32bit.
Posted on 2006-06-19 02:56:13 by Homer
IsWow64Process (from kernel32.dll), i dont think a 32 bit os would have that api? :)
Posted on 2006-06-19 04:08:16 by evlncrn8
OK, fair enough, GetProcAddr will fail for that api on a 32bit machine, and the technique requires no clever tricks.
If we ignore the fact that its a lot slower, then I'd have to say it's a much better way of doing this, especially since it's easy for beginners to understand and implement this way.

Posted on 2006-06-19 07:23:19 by Homer
Also, wouldn't a 64bit instruction *always* fail in a win32 app, regardless if it's running on XP64 or not?
Posted on 2006-06-19 07:26:24 by f0dder
a lot slower? the seh will be slow too, and on a 64 bit pc, such timing hardly matters... whats a few milliseconds, considering kernel32 will most likely be loaded anyways... and if speed is so critical you could code your own export walker for kernel32 and not use getprocaddress.....

getprocaddress - safer, requires no seh... and if you're going to use seh, then you also have to make sure the loadconfig stuff is setup right in the PE file... more overhead...
Posted on 2006-06-19 07:49:12 by evlncrn8

and if speed is so critical you could code your own export walker for kernel32 and not use getprocaddress.....

Which will probably be slower, unless you do quite some effort (hint: handling bound imports, binary search of exports, ...)

Posted on 2006-06-19 08:05:55 by f0dder
GetProcAddr that handles bound imports and uses a binary search can be found here http://www.asmcommunity.net/board/index.php?topic=17130.msg133137#msg133137

As for the original question: looking at MSDN it seems that using GetProcAddress for IsWow64Process (then calling it if is) is the done thing. There's an example on MSDN too (in C++) http://msdn.microsoft.com/library/en-us/dllproc/base/iswow64process.asp

You can also use GetNativeSystemInfo for more detailed information.
Posted on 2006-06-19 09:52:21 by stormix
I would think that GetSystemInfo would work in this case, you can determine the processor type and addressing range, if the processor is a 64bit and the address range is over 4GB then it's a 64 bit OS. The API is compatible down to NT3.5 and all of the 9x flavours so it won't fail the application.
Posted on 2006-06-19 12:36:06 by donkey
Ah, seems like the best bet is GetSystemInfo(), check if the wProcessorArchitecture field is equal to PROCESSOR_ARCHITECTURE_IA32_ON_WIN64.
Posted on 2006-06-19 16:39:33 by f0dder

Ah, seems like the best bet is GetSystemInfo(), check if the wProcessorArchitecture field is equal to PROCESSOR_ARCHITECTURE_IA32_ON_WIN64.



Apparently not...

MSDN says "To retrieve accurate information for an application running on WOW64, call the GetNativeSystemInfo function."

And I did some tests on WinXP x64 of the wProcessorArchitecure value:

GetSystemInfo from 32-bit app -> PROCESSOR_ARCHITECTURE_INTEL
GetSystemInfo from 64-bit app -> PROCESSOR_ARCHITECTURE_AMD64
GetNativeSystemInfo from 32-bit app -> PROCESSOR_ARCHITECTURE_AMD64
GetNativeSystemInfo from 64-bit app -> PROCESSOR_ARCHITECTURE_AMD64

This is strange though, when would it actually give you PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 then?

Posted on 2006-06-28 18:14:36 by stormix

This is strange though, when would it actually give you PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 then?

Pretty good question - in my mind, this would be the perfect return value from a 32bit app on win64. Perhaps it's for x86/win32 apps running on itanium/win64?
Posted on 2006-07-03 12:08:07 by f0dder
Maybe it's kind of backwards compatibility, where you have to -somehow- 'tell' the system, that your file is 'new', so it'll start returning you the true values - not the backward-compatible ones?
Posted on 2006-07-03 20:42:14 by ti_mo_n
I realize this is an old topic, but it seems there never really was a definitive answer (some posts are in the proper direction, but it still remains a tad vague).
Since I recently developed a 32-bit/64-bit launcher myself, I'll just briefly describe the way I go about it.

First, some things about Wow64:
1) Wow64 is Microsoft's name for the subsystem that runs a 32-bit application under a 64-bit OS.
2) Wow64 can run not only on x86-based processors, but also on Itanium (and perhaps others in the future).
3) GetSystemInfo() returns the information within the Wow64 environment, not the actual 64-bit OS environment.
4) An extra GetNativeSystemInfo() has been added to the API, which reports the actual 64-bit OS environment, even from a 32-bit application.
5) Wow64 can be detected by the IsWow64Process() function.
6) Both GetNativeSystemInfo() and IsWow64Process() have only recently been added to the kernel (around XP SP2 I believe), and as such may not be available.

Okay, with that background info, here's what I do (from a 32-bit process, obviously):
1) Use GetProcAddress() to load IsWow64Process().
1a) IsWow64Process() does not exist, assume we have a 32-bit OS. Done.

1b) IsWow64Process() exists, call IsWow64Process().
2a) IsWow64Process() returns false, we have a 32-bit OS. Done.

2b) IsWow64Process() returns true, we have a 64-bit OS.
3) Use GetProcAddress() to load GetNativeSystemInfo().
4) Call GetNativeSystemInfo and examine the architecture member. This tells us if we are running on Itanium or AMD64 (or maybe something else in the future...).

This should be a robust way to check for 32-bit x86, 64-bit x86 or 64-bit Itanium. I then use CreateProcess() to launch the most suitable binary for the platform.
(The GetProcAddress() calls are done because these functions do not exist in all versions of Windows. If you link to the functions directly, your executable wouldn't load on an older version of Windows. The functions are in kernel32.dll).

In theory it's not entirely 100%. Namely, you only know that 32-bit x86 processes run. In theory it could be that you are NOT using Wow64, but some other kind of emulation, rather than an actual x86 processor. I think that could be the case with Windows NT on an Alpha processor. However, I don't think it matters all that much. It just means in practice that you'll default to running the 32-bit x86 code when you don't know what architecture you're running on exactly (at least you know it's not IA64 or AMD64). The code will run, because you were checking from a 32-bit x86 process anyway.
I think at this point the only realistic options are x86, x64 and IA64 anyway. And for most intents and purposes, IA64 can be ignored. You'll rarely encounter them outside the server world.
Posted on 2009-07-07 03:39:12 by Scali
Thank you for writing this. Very clear explanation of the step by step checks for doing this. I won't be needing this right now for my projects but I'll keep it as a useful bookmark.

On another note, it doesn't matter to you that doing this delays the launch of the executable (and makes it bigger) ?
Posted on 2009-07-07 07:49:06 by ChaperonNoir
Well no, it doesn't really bother me :)
Not sure if you tried the files I posted in the other thread... but on a modern PC it loads so quickly that it seems instant. So the delay isn't an issue for me, it's in the order of milliseconds, not something you'd actually notice.
The size isn't either, because as you can see, the current version of the loader is 40 kb, becasue I just wrote it with C++, without bothering much about size. It was just a proof of concept. Since I already need to include both a 32-bit and 64-bit executable, and then a total of 6 DLLs for all the different combinations with D3D, an extra 40 kb doesn't really matter.

I suppose if I really wanted, I could get the loader down to maybe 1 kb in size, by writing my own string functions rather than using a C-lib, and with a bit of tweaking of the linker options.

I'll put the loader into the CPUInfo project on Sourceforge, as it's more or less related.
Posted on 2009-07-07 07:59:50 by Scali
The "loader" can be made as small as 4 kB (and use only kernel32.dll) if someone really needs it small and fast. So I don't think it's a big problem and it's nice to see that the app actually utilizes your hardware capabilities. Not that it really matters spped-wise but it's somewhat pleasing to know that those electrons are actually flowing through the higher 32-bits of those 64-bit registers ;p
Posted on 2009-07-10 19:10:24 by ti_mo_n