0

Is there any “global” code that can runs under both x86 and x64 architectures and determines the system architecture?(in assembly language) etc : in some operating system bootable setups the launcher can runs under both architectures

I want something like this:

if x86 jump x86architecture;
else jump x64architecture

I just want to detect the operating system architecture to build a program that can run under both architectures. not an operating system just a usual program that runs under an operating system. * I just don't want to get this error: "This version of this file is not compatible with the version of Windows you're running. Check your computer's system information to see whether you need an x86 (32-bit) or x64 (64-bit) version of the program, and then contact the software publisher."

someone
  • 5
  • 3
  • 2
    You generally always know what mode your CPU is currently in, but you can write machine code that branches depending on the current mode: [x86-32 / x86-64 polyglot machine-code fragment that detects 64bit mode at run-time?](https://stackoverflow.com/q/38063529). Not sure if that's what you mean, or if you just want what the CPU is *capable* of, e.g. for a 16 or 32-bit bootloader to choose to load a 64-bit or 32-bit kernel. – Peter Cordes Apr 02 '20 at 14:46
  • You can do that if-then-else but that alone won't change the mode. – Erik Eidt Apr 02 '20 at 14:48
  • That's a totally different question. You just need a 32-bit program that can check if it's running under 64-bit Windows. Like [Detect whether current Windows version is 32 bit or 64 bit](https://stackoverflow.com/q/601089) or [Detect 32-bit or 64-bit of Windows](https://stackoverflow.com/q/7011071). You can make WinAPI DLL calls from assembly. Note that using CPUID is not sufficient; 32-bit Windows can't run 64-bit programs even on 64-bit-capable hardware. – Peter Cordes Apr 03 '20 at 12:00

1 Answers1

1

A PC boots in real mode (16 bit mode) or 32 bit protected mode depending on whether you boot in legacy mode (MBR) or EFI mode. An operating system can then switch to any other mode it likes. You can find out if the CPU supports long mode (64 bit mode) by checking cpuid.

32 bit mode is supported if your CPU is an 80386 or newer. You can find out if it is by toggling some bits in the flags register.

To detect the availability of long mode, execute a cpuid instruction and check for bit 29 in EDX with EAX=0x80000001:

mov eax, 800000001h    ; select leaf 80000001
cpuid                  ; load CPU 
bt edx, 29             ; is bit 29 set in edx?
jc long_mode_available ; if yes, long mode is available
                       ; otherwise it is not

Note that you must first check if CPUID is available or this code might cause a crash. Refer to this section for details on how to detect the availability of long mode.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • I just want to detect the operating system architecture to build a program that can run under both architectures. not an operating system just a usual program that runs under an operating system. * I just don't want to get this error: "This version of this file is not compatible with the version of Windows you're running. Check your computer's system information to see whether you need an x86 (32-bit) or x64 (64-bit) version of the program, and then contact the software publisher." – someone Apr 03 '20 at 08:06
  • 2
    @someone You should have said so in the first place. This is rather tricky but probably not impossible. Any solution is also going to be extremely specific to Windows. Why didn't you mention Windows or that this was what you are trying to achieve? – fuz Apr 03 '20 at 11:22
  • @someone I have not voted to close your question. I think the key problem is that you have misunderstood how CPU operating modes work. When you write a 16 bit program, the program always starts in 16 bit mode. When you write a 32 bit program, it always starts in 32 bit mode and when you write a 64 bit program, it always starts in 64 bit mode. Therefore, it makes no sense to detect the current operating mode; it's always going to be the same mode your program was compiled or assembled for. – fuz Apr 03 '20 at 16:47
  • @someone It is possible to generate Windows binaries that contain both a 16 bit program and a separate 32 bit program. If 32 bit mode is supported (i.e. on Windows 95 or newer), Windows will try to start the 32 bit program. Older versions of Windows try to start the 16 bit program instead. In the 32 bit program, you could then start a separate 64 bit program if 64 bit mode is supported, but I don't really see the point in that. If you want to write a program that runs on all Windows versions since Windows 95, simply write a 32 bit program and you are good to go. – fuz Apr 03 '20 at 16:49
  • @someone Also, the second question linked references the Windows API function `IsWow64Process`. You can call that function from assembly just fine. In fact, there is nothing C++ specific in that question at all. Both linked questions of course find out what type of Windows installation (32 or 64 bit) your code is running on because Peter Cordes figured out that might be what you meant. 32 bit Windows can run 16 bit and 32 bit programs. 64 bit Windows can run 32 bit and 64 bit programs. On both versions, the CPU is in 32 bit mode when it runs a 32 bit program. – fuz Apr 03 '20 at 16:53
  • @someone And lastly: the error message you receive likely indicates that you try to run a 16 bit program on a 64 bit system. This is not supported and there is no way to make this work. Simply write a 32 bit program instead and it's going to work on all Windows versions since Windows 95. – fuz Apr 03 '20 at 16:55