C (gcc), x64 only, 37 bytes
asm("m:_m:.int 50066");f(){m(2,1,0);}
Try it online!
Function called f()
. Returns 1
for Windows, 0
for non-Windows.
You wanted a "creative solution"? Here you go. Unfortunately, it isn't as short or portable as the other C solution. (TODO: x86, ARM, and ARM64 polyglot /s)
Expanded:
// ASM
// We need both m and _m because macOS uses leading underscores for
// C symbols, while Windows and Linux do not.
m:
_m:
// We manually encode these in the golfed code to save space.
// eax = edx
xchg eax, edx // 0x92
ret // 0xC3
// C
int m(int, int, int);
int f()
{
// The first parameter can be anything, I use 2 for ease of explanation.
return m(2, 1, 0);
}
What does it do? It uses the fact that Windows and Linux (and Mac, BSD, etc) use different calling conventions on x64.
So, when GCC tries to call m(2, 1, 0)
, on Windows it will use the Microsoft x64 calling convention (rcx
, rdx
, r8
, r9
):
mov ecx, 2
mov edx, 1
mov r8d, 0
call m
However, on Linux, Mac, BSD, etc, it will use the System V calling convention (rdi
, rsi
, rdx
, rcx
, r8
, r9
):
mov edi, 2
mov esi, 1
mov edx, 0
call m
As I have bolded, edx
is used on both platforms, but since they represent different parameters in the calling conventions, Windows and non-Windows will get different values.
With some inline assembly, we can get GCC to return the value of edx
instead of the third parameter.
To test how it would function on Windows, simply uncomment the prototype at the top, which uses an attribute to force GCC to use the Microsoft ABI.