x86 16/32/64ビットマシンコード:11バイト、スコア= 3.66
この関数は、現在のモード(デフォルトのオペランドサイズ)をALの整数として返します。署名付きでCから呼び出すuint8_t modedetect(void);
NASMマシンコード+ソースリスト(16ビットモードBITS 16のソースニーモニックをアセンブルするようNASMに指示するため、16ビットモードでの動作を示す)
 1          machine      global modedetect
 2          code         modedetect:
 3 addr     hex          BITS 16
 5 00000000 B040             mov    al, 64
 6 00000002 B90000           mov    cx, 0       ; 3B in 16-bit.  5B in 32/64, consuming 2 more bytes as the immediate
 7 00000005 FEC1             inc    cl          ; always 2 bytes.  The 2B encoding of inc cx would work, too.
 8                       
 9                           ; want: 16-bit cl=1.   32-bit: cl=0
10 00000007 41               inc    cx       ; 64-bit: REX prefix
11 00000008 D2E8             shr    al, cl   ; 64-bit: shr r8b, cl doesn't affect AL at all.  32-bit cl=1.  16-bit cl=2
12 0000000A C3               ret
# end-of-function address is 0xB, length = 0xB = 11
正当化:
x86マシンコードには正式なバージョン番号はありませんが、これは最も便利なもの(7バイトしかかからない、以下を参照)を選択するのではなく、特定の番号を生成することで質問の意図を満たしていると思います。
元のx86 CPUであるIntelの8086は、16ビットのマシンコードのみをサポートしていました。80386は32ビットのマシンコードを導入しました(32ビットの保護モードで使用でき、後で64ビットOSの互換モードで使用できます)。AMDは、ロングモードで使用可能な64ビットマシンコードを導入しました。これらは、Python2とPython3が異なる言語バージョンであるという同じ意味でのx86マシン言語のバージョンです。ほとんど互換性がありますが、意図的に変更されています。Python2およびPython3プログラムを実行するのと同じ方法で、32ビットまたは64ビットの実行可能ファイルを64ビットOSカーネルの下で直接実行できます。
使い方:
で始まりal=64ます。1(32ビットモード)または2(16ビットモード)だけ右にシフトします。
- 16/32対64ビット:1バイト- inc/- decエンコーディングは、64ビットのREXプレフィックスです(http://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix)。REX.Wは一部の命令にまったく影響を与えません(たとえば、a- jmpまたは- jcc)が、この場合は16/32/64 を取得するために、- ecxでなくincまたはdecにしたかったのです- eax。また、が設定- REX.Bされ、宛先レジスタが変更されます。しかし幸いなことに、私たちはそれを機能させることができますが、64ビットがシフトする必要がないように設定します- al。
 - 16ビットモードでのみ実行される命令にはを含めることができますが- ret、その必要性や有用性はわかりませんでした。(そして、あなたがそれをしたい場合には、コードフラグメントとしてインライン化することを不可能にします)。また、可能性が- jmp関数内。
 
- 16ビットと32/64:イミディエートは32ビットではなく16ビットです。モードを変更すると、命令の長さが変わる可能性があるため、32/64ビットモードでは、個別の命令ではなく、イミディエイトの一部として次の2バイトをデコードします。16ビットモードで32/64とは異なる命令境界からデコードするように、デコードを同期から外すのではなく、ここで2バイトの命令を使用することにより、物事をシンプルにしました。 - 関連:オペランドサイズのプレフィックスは、16ビットモードと32/64ビットモードの違いのように、即値の長さを変更します(符号拡張された8ビットの即値でない限り)。これにより、命令長のデコードを並行して行うことが難しくなります。Intel CPUにはLCPデコードストールがあります。 
ほとんどの呼び出し規約(x86-32およびx86-64 System V psABIを含む)では、狭い戻り値でレジスターの上位ビットにガーベッジを含めることができます。また、CX / ECX / RCX(および64ビットのR8)を上書きすることもできます。IDKは、16ビットの呼び出し規則では一般的でしたが、これはコードゴルフなので、とにかくカスタム呼び出し規則であると言うことができます。
32ビット逆アセンブリ:
08048070 <modedetect>:
 8048070:       b0 40                   mov    al,0x40
 8048072:       b9 00 00 fe c1          mov    ecx,0xc1fe0000   # fe c1 is the inc cl
 8048077:       41                      inc    ecx         # cl=1
 8048078:       d2 e8                   shr    al,cl
 804807a:       c3                      ret    
64ビットの逆アセンブリ(オンラインで試してみてください!):
0000000000400090 <modedetect>:
  400090:       b0 40                   mov    al,0x40
  400092:       b9 00 00 fe c1          mov    ecx,0xc1fe0000
  400097:       41 d2 e8                shr    r8b,cl      # cl=0, and doesn't affect al anyway!
  40009a:       c3                      ret    
関連:SOでのx86-32 / x86-64ポリグロットマシンコード Q&A
16ビットと32/64のもう1つの違いは、アドレス指定モードのエンコード方法が異なることです。例lea  eax, [rax+2](8D 40 02)lea ax, [bx+si+0x2]16ビットモードのようにデコードします。これは、特に以来、明らかにコードゴルフのために使用することは困難であるe/rbxとe/rsi多くの呼び出し規約では、コール保存されています。
またmov r64, imm64、REX +である10バイトの使用を検討しましたmov r32,imm32。しかし、私はすでに11バイトのソリューションを持っているので、これはせいぜい等しい(10バイト+の場合は1 ret)でしょう。
32および64ビットモードのテストコード。(実際に16ビットモードで実行したことはありませんが、逆アセンブリではデコード方法が示されます。16ビットエミュレーターがセットアップされていません。)
; CPU p6   ;  YASM directive to make the ALIGN padding tidier
global _start
_start:
    call   modedetect
    movzx  ebx, al
    mov    eax, 1
    int    0x80        ; sys_exit(modedetect());
align 16
modedetect:
BITS 16
    mov    al, 64
    mov    cx, 0       ; 3B in 16-bit.  5B in 32/64, consuming 2 more bytes as the immediate
    inc    cl          ; always 2 bytes.  The 2B encoding of inc cx would work, too.
    ; want: 16-bit cl=1.   32-bit: cl=0
    inc    cx       ; 64-bit: REX prefix
    shr    al, cl   ; 64-bit: shr r8b, cl doesn't affect AL at all.  32-bit cl=1.  16-bit cl=2
    ret
このLinuxプログラムはexit-status = modedetect()で終了するため、として実行します./a.out;  echo $?。静的バイナリにアセンブルしてリンクします。例えば
$ asm-link -m32 x86-modedetect-polyglot.asm && ./x86-modedetect-polyglot; echo $?
+ yasm -felf32 -Worphan-labels -gdwarf2 x86-modedetect-polyglot.asm
+ ld -melf_i386 -o x86-modedetect-polyglot x86-modedetect-polyglot.o
32
$ asm-link -m64 x86-modedetect-polyglot.asm && ./x86-modedetect-polyglot; echo $?
+ yasm -felf64 -Worphan-labels -gdwarf2 x86-modedetect-polyglot.asm
+ ld -o x86-modedetect-polyglot x86-modedetect-polyglot.o
64
## maybe test 16-bit with BOCHS somehow if you really want to.
バージョン1、2、3に番号を付けることができる場合、7バイト(スコア= 2.33)
さまざまなx86モードの公式バージョン番号はありません。asmの回答を書くのが好きです。モード1、2、3、または0、1、2を呼び出しただけでは、不便な番号を生成するように強制することになるため、質問の意図に反すると思います。しかし、それが許可された場合:
 # 16-bit mode:
42                                  detect123:
43 00000020 B80300                      mov ax,3
44 00000023 FEC8                        dec al
45                                  
46 00000025 48                          dec ax
47 00000026 C3                          ret
32ビットモードでデコードするもの 
08048080 <detect123>:
 8048080:       b8 03 00 fe c8          mov    eax,0xc8fe0003
 8048085:       48                      dec    eax
 8048086:       c3                      ret    
および64ビットとして
00000000004000a0 <detect123>:
  4000a0:       b8 03 00 fe c8          mov    eax,0xc8fe0003
  4000a5:       48 c3                   rex.W ret