Is my OS 32-bit or 64-bit?

x86 machine code, 12 bytes

8c c8 83 f8 23 b0 20 75 02 00 c0 c3

Ungolfed:

getKernelBitness:
    mov eax,cs
    cmp eax,0x23 ; 32 bit process on 64 bit kernel has this selector in CS
    mov al,32
    jne kernelIs32Bit
    add al,al    ; return value in eax
kernelIs32Bit:
    ret

This function works in Linux when used in ELF32, following i386 SysV ABI, as well as in Windows/Wine when used in PE32, following stdcall calling convention.


x86 Assembly (polyglot), 13 bytes

Bytecode:

31 c0 b4 80 48 70 05 04 40 83 e0 60 c3

Defines a function which returns 32 if interpreted as 32-bit, 64 if 64-bit, and 32767 if 16-bit.

I wanted to make a polyglot which ran on Windows and Linux, but this is a lot harder than I thought. As it is I'm not sure there's even any way to print a value on non-16-bit Windows without linking.

Explanation

This code uses two tells to determine the architecture it is running on. The first is the instruction 0x48—on 16 and 32 bits, this is dec %eax, but on 64 bits, it is an instruction-size prefix. The second tell is the same instruction, however, when we execute it on the value 0x8000, the most significant bit is flipped only if the register size is 16 bits, setting the overflow flag and letting us use jo.

In 16 bits, this code is interpreted as the following:

   0:   31 c0                   xor    %ax,%ax    /* 0x0000 */
   2:   b4 80                   mov    $0x80,%ah  /* 0x8000 */
   4:   48                      dec    %ax        /* 0x7fff */
   5:   70 05                   jo c              /* taken  */
   7:   04 40                   add    $0x40,%al
   9:   83 e0 60                and    $0x60,%ax
   c:   c3                      ret               /* 0x7fff */

In 32 bits, this code is interpreted as the following:

   0:   31 c0                   xor    %eax,%eax   /* 0x00000000 */
   2:   b4 80                   mov    $0x80,%ah   /* 0x00008000 */
   4:   48                      dec    %eax        /* 0x00007fff */
   5:   70 05                   jo c               /* not taken  */
   7:   04 40                   add    $0x40,%al   /* 0x00007f3f */
   9:   83 e0 60                and    $0x60,%eax  /* 0x00000020 */
   c:   c3                      ret

In 64 bits, this code is interpreted as the following:

   0:   31 c0                   xor    %eax,%eax   /* 0x00000000 */
   2:   b4 80                   mov    $0x80,%ah   /* 0x00008000 */
   4:   48 70 05                rex.W jo c         /* not taken  */
   7:   04 40                   add    $0x40,%al   /* 0x00008040 */
   9:   83 e0 60                and    $0x60,%eax  /* 0x00000040 */
   c:   c3                      ret

Mathematica, 17 bytes

$SystemWordLength