CODE blog (アンテナ) どころか tDiary で書くのも初めて、ってことで、練習を兼ねて。
x86, IA-32 というと 80386 互換プロセッサだと思って間違いない (?) んですが、 486 で追加された命令、Pentium 4 で追加された命令等々があって、 例えば Pentium 4 以降向けにコンパイルされたバイナリが、 より古いプロセッサでは動かなかったりするわけです。 こういった命令としては SIMD 命令、つまり MMX, SSE, SSE2 命令が有名ですが、 それ以外にもちょこちょことあります。
そういった命令にはどんなものがあったけな?というときに僕が見るのが、 binutils に入ってる i386.h。例えばこんな感じです。
binutils-2.16.1/include/opcode/i386.h:557-558
557: /* i386sl, i486sl, later 486, and Pentium. */ 558: {"rsm", 0, 0x0faa, X, Cpu386, NoSuf, { 0, 0, 0} },
binutils-2.16.1/include/opcode/i386.h:894-901
bswap は、htonl(3)、ntohl(3) で使われてます。 cmpxchg (compare and exchange) はロック関係の実装に使われます。894: /* 486 extensions. */ 895: 896: {"bswap", 1, 0x0fc8, X, Cpu486, lq_Suf|ShortForm, { Reg32|Reg64, 0, 0 } }, 897: {"xadd", 2, 0x0fc0, X, Cpu486, bwlq_Suf|W|Modrm, { Reg, Reg|AnyMem, 0 } }, 898: {"cmpxchg", 2, 0x0fb0, X, Cpu486, bwlq_Suf|W|Modrm, { Reg, Reg|AnyMem, 0 } }, 899: {"invd", 0, 0x0f08, X, Cpu486, NoSuf, { 0, 0, 0} }, 900: {"wbinvd", 0, 0x0f09, X, Cpu486, NoSuf, { 0, 0, 0} }, 901: {"invlpg", 1, 0x0f01, 7, Cpu486, NoSuf|Modrm|IgnoreSize, { AnyMem, 0, 0} },
binutils-2.16.1/include/opcode/i386.h:903-910
rdtsc は、1クロックあたり1だけ増やされるカウンタの値を取得できます。 つまり、クロック単位での時間計測に使えます。 akr さんが大好き (?) な命令です。903: /* 586 and late 486 extensions. */ 904: {"cpuid", 0, 0x0fa2, X, Cpu486, NoSuf, { 0, 0, 0} }, 905: 906: /* Pentium extensions. */ 907: {"wrmsr", 0, 0x0f30, X, Cpu586, NoSuf, { 0, 0, 0} }, 908: {"rdtsc", 0, 0x0f31, X, Cpu586, NoSuf, { 0, 0, 0} }, 909: {"rdmsr", 0, 0x0f32, X, Cpu586, NoSuf, { 0, 0, 0} }, 910: {"cmpxchg8b",1,0x0fc7, 1, Cpu586, q_Suf|Modrm, { LLongMem, 0, 0} },
binutils-2.16.1/include/opcode/i386.h:912-980
sysenter/sysexit は、システムコール呼び出しを高速化するために用意された命令です。 cmov*, fcmov* は、条件付 move 命令です。912: /* Pentium II/Pentium Pro extensions. */ 913: {"sysenter",0, 0x0f34, X, Cpu686, NoSuf, { 0, 0, 0} }, 914: {"sysexit", 0, 0x0f35, X, Cpu686, NoSuf, { 0, 0, 0} }, 915: {"fxsave", 1, 0x0fae, 0, Cpu686, q_Suf|Modrm, { LLongMem, 0, 0} }, 916: {"fxrstor", 1, 0x0fae, 1, Cpu686, q_Suf|Modrm, { LLongMem, 0, 0} }, 917: {"rdpmc", 0, 0x0f33, X, Cpu686, NoSuf, { 0, 0, 0} }, 918: /* official undefined instr. */ 919: {"ud2", 0, 0x0f0b, X, Cpu686, NoSuf, { 0, 0, 0} }, 920: /* alias for ud2 */ 921: {"ud2a", 0, 0x0f0b, X, Cpu686, NoSuf, { 0, 0, 0} }, 922: /* 2nd. official undefined instr. */ 923: {"ud2b", 0, 0x0fb9, X, Cpu686, NoSuf, { 0, 0, 0} }, 924: 925: {"cmovo", 2, 0x0f40, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 926: {"cmovno", 2, 0x0f41, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 927: {"cmovb", 2, 0x0f42, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 928: {"cmovc", 2, 0x0f42, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 929: {"cmovnae", 2, 0x0f42, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 930: {"cmovae", 2, 0x0f43, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 931: {"cmovnc", 2, 0x0f43, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 932: {"cmovnb", 2, 0x0f43, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 933: {"cmove", 2, 0x0f44, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 934: {"cmovz", 2, 0x0f44, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 935: {"cmovne", 2, 0x0f45, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 936: {"cmovnz", 2, 0x0f45, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 937: {"cmovbe", 2, 0x0f46, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 938: {"cmovna", 2, 0x0f46, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 939: {"cmova", 2, 0x0f47, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 940: {"cmovnbe", 2, 0x0f47, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 941: {"cmovs", 2, 0x0f48, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 942: {"cmovns", 2, 0x0f49, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 943: {"cmovp", 2, 0x0f4a, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 944: {"cmovnp", 2, 0x0f4b, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 945: {"cmovl", 2, 0x0f4c, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 946: {"cmovnge", 2, 0x0f4c, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 947: {"cmovge", 2, 0x0f4d, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 948: {"cmovnl", 2, 0x0f4d, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 949: {"cmovle", 2, 0x0f4e, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 950: {"cmovng", 2, 0x0f4e, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 951: {"cmovg", 2, 0x0f4f, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 952: {"cmovnle", 2, 0x0f4f, X, Cpu686, wlq_Suf|Modrm, { WordReg|WordMem, WordReg, 0} }, 953: 954: {"fcmovb", 2, 0xdac0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 955: {"fcmovnae",2, 0xdac0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 956: {"fcmove", 2, 0xdac8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 957: {"fcmovbe", 2, 0xdad0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 958: {"fcmovna", 2, 0xdad0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 959: {"fcmovu", 2, 0xdad8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 960: {"fcmovae", 2, 0xdbc0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 961: {"fcmovnb", 2, 0xdbc0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 962: {"fcmovne", 2, 0xdbc8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 963: {"fcmova", 2, 0xdbd0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 964: {"fcmovnbe",2, 0xdbd0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 965: {"fcmovnu", 2, 0xdbd8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 966: 967: {"fcomi", 2, 0xdbf0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 968: {"fcomi", 0, 0xdbf1, X, Cpu686, FP|ShortForm, { 0, 0, 0} }, 969: {"fcomi", 1, 0xdbf0, X, Cpu686, FP|ShortForm, { FloatReg, 0, 0} }, 970: {"fucomi", 2, 0xdbe8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 971: {"fucomi", 0, 0xdbe9, X, Cpu686, FP|ShortForm, { 0, 0, 0} }, 972: {"fucomi", 1, 0xdbe8, X, Cpu686, FP|ShortForm, { FloatReg, 0, 0} }, 973: {"fcomip", 2, 0xdff0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 974: {"fcompi", 2, 0xdff0, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 975: {"fcompi", 0, 0xdff1, X, Cpu686, FP|ShortForm, { 0, 0, 0} }, 976: {"fcompi", 1, 0xdff0, X, Cpu686, FP|ShortForm, { FloatReg, 0, 0} }, 977: {"fucomip", 2, 0xdfe8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 978: {"fucompi", 2, 0xdfe8, X, Cpu686, FP|ShortForm, { FloatReg, FloatAcc, 0} }, 979: {"fucompi", 0, 0xdfe9, X, Cpu686, FP|ShortForm, { 0, 0, 0} }, 980: {"fucompi", 1, 0xdfe8, X, Cpu686, FP|ShortForm, { FloatReg, 0, 0} },
binutils-2.16.1/include/opcode/i386.h:982-988
982: /* Pentium4 extensions. */ 983: 984: {"movnti", 2, 0x0fc3, X, CpuP4, wlq_Suf|Modrm, { WordReg, WordMem, 0 } }, 985: {"clflush", 1, 0x0fae, 7, CpuP4, NoSuf|Modrm|IgnoreSize, { ByteMem, 0, 0 } }, 986: {"lfence", 0, 0x0fae, 0xe8, CpuP4, NoSuf|ImmExt, { 0, 0, 0 } }, 987: {"mfence", 0, 0x0fae, 0xf0, CpuP4, NoSuf|ImmExt, { 0, 0, 0 } }, 988: {"pause", 0, 0xf390, X, CpuP4, NoSuf, { 0, 0, 0 } },
binutils-2.16.1/include/opcode/i386.h:1374-1384
1374: /* VIA PadLock extensions. */ 1375: {"xstorerng", 0, 0x000fa7c0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1376: {"xcryptecb", 0, 0xf30fa7c8, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1377: {"xcryptcbc", 0, 0xf30fa7d0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1378: {"xcryptcfb", 0, 0xf30fa7e0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1379: {"xcryptofb", 0, 0xf30fa7e8, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1380: {"montmul", 0, 0xf30fa6c0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1381: {"xsha1", 0, 0xf30fa6c8, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1382: {"xsha256", 0, 0xf30fa6d0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} }, 1383: /* Alias for xstorerng. */ 1384: {"xstore", 0, 0x000fa7c0, X, Cpu686|CpuPadLock, NoSuf|IsString, { 0, 0, 0} },