1

Other than the more common instructions like mov, add, call, ...etc I was curious about which instructions are most commonly used out of the 1500 or so instructions (it seems like 15 million). I wrote the following one-liner to check the counts of some common linux programs in python (it can be used with just changing the path of the executable in the script):

# need lxml installed: https://pypi.org/project/lxml/
$ python -c "import re,subprocess,requests; from lxml import html;xmap={x.text.lower(): 'https://www.felixcloutier.com/x86/' + x.attrib['href'] for x in html.fromstring(requests.get('https://www.felixcloutier.com/x86/index.html').content).xpath('//td/a')}; from collections import Counter; print('\n'.join([f'{k+1:>4}. {v[0]:<8} - {v[1]} - {xmap.get(v[0])}' for k,v in enumerate(Counter(re.findall(r'\t(\w{3,9})', subprocess.check_output('objdump -d -Mintel /bin/ls', shell=True).decode('utf-8'))).most_common())]))"

And it gives me:

   1. mov      - 5734 - https://www.felixcloutier.com/x86/./MOV-2.html
   2. cmp      - 1236 - https://www.felixcloutier.com/x86/./CMP.html
   3. call     - 1137 - https://www.felixcloutier.com/x86/./CALL.html
   4. jmp      - 1115 - https://www.felixcloutier.com/x86/./JMP.html
   5. nop      - 959 - https://www.felixcloutier.com/x86/./NOP.html
   6. test     - 949 - https://www.felixcloutier.com/x86/./TEST.html
   7. lea      - 909 - https://www.felixcloutier.com/x86/./LEA.html
   8. xor      - 769 - https://www.felixcloutier.com/x86/./XOR.html
   9. jne      - 717 - None
  10. pop      - 682 - https://www.felixcloutier.com/x86/./POP.html
  11. push     - 646 - https://www.felixcloutier.com/x86/./PUSH.html
  12. add      - 570 - https://www.felixcloutier.com/x86/./ADD.html
  13. sub      - 381 - https://www.felixcloutier.com/x86/./SUB.html
  14. movzx    - 267 - https://www.felixcloutier.com/x86/./MOVZX.html
  15. ret      - 263 - https://www.felixcloutier.com/x86/./RET.html
  16. sete     - 158 - None
  17. and      - 155 - https://www.felixcloutier.com/x86/./AND.html
  18. jbe      - 118 - None
  19. xchg     - 88 - https://www.felixcloutier.com/x86/./XCHG.html
  20. repz     - 83 - https://www.felixcloutier.com/x86/./REP:REPE:REPZ:REPNE:REPNZ.html
  21. jae      - 82 - None
  22. movsxd   - 59 - https://www.felixcloutier.com/x86/./MOVSX:MOVSXD.html
  23. cmove    - 58 - None
  24. shr      - 53 - https://www.felixcloutier.com/x86/./SAL:SAR:SHL:SHR.html
  25. sar      - 46 - https://www.felixcloutier.com/x86/./SAL:SAR:SHL:SHR.html
  26. mul      - 43 - https://www.felixcloutier.com/x86/./MUL.html
  27. imul     - 40 - https://www.felixcloutier.com/x86/./IMUL.html
  28. shl      - 38 - https://www.felixcloutier.com/x86/./SAL:SAR:SHL:SHR.html
  29. jle      - 33 - None
  30. setne    - 32 - None
  31. movabs   - 29 - None
  32. div      - 28 - https://www.felixcloutier.com/x86/./DIV.html
  33. sbb      - 24 - https://www.felixcloutier.com/x86/./SBB.html
  34. pxor     - 24 - https://www.felixcloutier.com/x86/./PXOR.html
  35. fstp     - 22 - https://www.felixcloutier.com/x86/./FST:FSTP.html
  36. cmovne   - 21 - None
  37. movsx    - 20 - https://www.felixcloutier.com/x86/./MOVSX:MOVSXD.html
  38. cvtsi2ss - 20 - https://www.felixcloutier.com/x86/./CVTSI2SS.html
  39. jns      - 18 - None
  40. ucomiss  - 18 - https://www.felixcloutier.com/x86/./UCOMISS.html
  41. fld      - 18 - https://www.felixcloutier.com/x86/./FLD.html
  42. movdqa   - 15 - https://www.felixcloutier.com/x86/./MOVDQA:VMOVDQA32:VMOVDQA64.html
  43. not      - 14 - https://www.felixcloutier.com/x86/./NOT.html
  44. cmovae   - 14 - None
  45. cmovns   - 13 - None
  46. cdqe     - 11 - https://www.felixcloutier.com/x86/./CBW:CWDE:CDQE.html
  47. addss    - 11 - https://www.felixcloutier.com/x86/./ADDSS.html
  48. movups   - 10 - https://www.felixcloutier.com/x86/./MOVUPS.html
  49. movss    - 10 - https://www.felixcloutier.com/x86/./MOVSS.html
  50. movaps   - 10 - https://www.felixcloutier.com/x86/./MOVAPS.html
  51. jge      - 8 - None
  52. setb     - 8 - None
  53. cvttss2si - 8 - https://www.felixcloutier.com/x86/./CVTTSS2SI.html
  54. mulss    - 8 - https://www.felixcloutier.com/x86/./MULSS.html
  55. neg      - 7 - https://www.felixcloutier.com/x86/./NEG.html
  56. cmovs    - 6 - None
  57. fild     - 6 - https://www.felixcloutier.com/x86/./FILD.html
  58. fadd     - 5 - https://www.felixcloutier.com/x86/./FADD:FADDP:FIADD.html
  59. setl     - 5 - None
  60. cmovb    - 4 - None
  61. seta     - 4 - None
  62. movdqu   - 4 - https://www.felixcloutier.com/x86/./MOVDQU:VMOVDQU8:VMOVDQU16:VMOVDQU32:VMOVDQU64.html
  63. cvtsi2sd - 4 - https://www.felixcloutier.com/x86/./CVTSI2SD.html
  64. subss    - 4 - https://www.felixcloutier.com/x86/./SUBSS.html
  65. fldcw    - 4 - https://www.felixcloutier.com/x86/./FLDCW.html
  66. fxch     - 4 - https://www.felixcloutier.com/x86/./FXCH.html
  67. fucomip  - 4 - https://www.felixcloutier.com/x86/./FCOMI:FCOMIP:FUCOMI:FUCOMIP.html
  68. fmul     - 4 - https://www.felixcloutier.com/x86/./FMUL:FMULP:FIMUL.html
  69. seto     - 4 - None
  70. jno      - 4 - None
  71. setg     - 3 - None
  72. cmovl    - 3 - None
  73. mulsd    - 2 - https://www.felixcloutier.com/x86/./MULSD.html
  74. addsd    - 2 - https://www.felixcloutier.com/x86/./ADDSD.html
  75. divss    - 2 - https://www.felixcloutier.com/x86/./DIVSS.html
  76. fucomi   - 2 - https://www.felixcloutier.com/x86/./FCOMI:FCOMIP:FUCOMI:FUCOMIP.html
  77. fnstcw   - 2 - https://www.felixcloutier.com/x86/./FSTCW:FNSTCW.html
  78. fistp    - 2 - https://www.felixcloutier.com/x86/./FIST:FISTP.html
  79. fdivrp   - 2 - https://www.felixcloutier.com/x86/./FDIVR:FDIVRP:FIDIVR.html
  80. repnz    - 1 - https://www.felixcloutier.com/x86/./REP:REPE:REPZ:REPNE:REPNZ.html
  81. hlt      - 1 - https://www.felixcloutier.com/x86/./HLT.html
  82. setbe    - 1 - None
  83. movs     - 1 - https://www.felixcloutier.com/x86/./MOVS:MOVSB:MOVSW:MOVSD:MOVSQ.html
  84. cmovbe   - 1 - None
  85. rep      - 1 - https://www.felixcloutier.com/x86/./REP:REPE:REPZ:REPNE:REPNZ.html
  86. cmovge   - 1 - None
  87. ror      - 1 - https://www.felixcloutier.com/x86/./RCL:RCR:ROL:ROR.html
  88. divsd    - 1 - https://www.felixcloutier.com/x86/./DIVSD.html
  89. fsub     - 1 - https://www.felixcloutier.com/x86/./FSUB:FSUBP:FISUB.html
  90. fmulp    - 1 - https://www.felixcloutier.com/x86/./FMUL:FMULP:FIMUL.html
  91. fdivp    - 1 - https://www.felixcloutier.com/x86/./FDIV:FDIVP:FIDIV.html
  92. cmova    - 1 - None
  93. cmovg    - 1 - None
  94. cmovle   - 1 - None
  95. cdq      - 1 - https://www.felixcloutier.com/x86/./CWD:CDQ:CQO.html
  96. idiv     - 1 - https://www.felixcloutier.com/x86/./IDIV.html
  97. rol      - 1 - https://www.felixcloutier.com/x86/./RCL:RCR:ROL:ROR.html

I should probably group the instructions a bit better, so that the cc items find its proper link (for example setbe --> setcc). And the odd thing is, being a super novice in assembly, most of the instructions look pretty familiar to me (not like about 90% of them on the Intel manual page).

So my question for this is what is the context of most of the more-esoteric x86 instructions? I suppose perhaps a graphics or weather forecasting system could make use out of 100% of the floating point instructions. But how do these instructions come about -- are all of them used by different industries when combined together, for example?

David542
  • 104,438
  • 178
  • 489
  • 842
  • First off you are operating under the assumption that this was a clean/accurate disassembly? Which for x86 is difficult at best. Compiled code tends to use the same types of instructions, a particular tool has favorite or prioritized instructions where other tools may use a different mix. – old_timer Sep 27 '20 at 04:30
  • @old_timer: For non-obfuscated compiler-generated binaries (like `/bin/ls` on a GNU/Linux system), it's pretty trivial. `objdump -d` does reliably disassemble the instructions that will actually run, because you don't have data in the `.text` section throwing things off. – Peter Cordes Sep 27 '20 at 04:32
  • I have demonstrated here how easy it is to defeat objdump for x86, in fact rarely do I see it do an accurate job. It does not do an executable order disassembly it does a linear disassembly and if not stripped uses labels to periodically reset without caring that it was confused. – old_timer Sep 27 '20 at 04:34
  • 1
    `/bin/ls` was probably only compiled with `gcc -O2` optimization (not `-O3` so no auto-vectorization), and probably doesn't have a lot of loops that could auto-vectorize anyway. So it's only using SSE2 instructions for data transfer. Also, many of the 1500 existing instructions require AVX512, AVX1/2, or some SSE version greater than 2, but only SSE2 and earlier are "baseline" available for generic x86-64 builds like normal distros make. So anyway, GCC -O2 is only going to use SSE2 `movaps` / `movups` and `pxor`-zeroing for data copying and initialization. – Peter Cordes Sep 27 '20 at 04:35
  • You cant really do any statistics until you have insured that your data is good, and then you land in the situation that a particular tool heavily uses some instructions and others dont. for compiled langauges where you have different compilers you will find depending on the authors, heavy use of different instructions between the tools. I used this fact to test processors when I was doing that. It found bugs in the core. – old_timer Sep 27 '20 at 04:36
  • I was surprised to see `fmul` and other x87 instructions in the disassembly, but I can reproduce that on Arch GNU/Linux; `/bin/ls` includes some code that seems to be doing `long double` math, so it uses x87. I'm not sure what it's doing, but the sequence of instructions appears sane, no sign of it being "out of sync" like the old_timer is warning about. I've never seen that happen with vanilla compiler output without any hand-written asm, and there's good reason to not expect any. Read-only data goes in `section .rodata` so it doesn't get disassembled as code. – Peter Cordes Sep 27 '20 at 04:42
  • @PeterCordes out of (more) curiosity, why is `nop` used so much in compiler-generated code? Is it all for padding/placeholder? – David542 Sep 27 '20 at 04:48
  • 1
    @David542: Yes, gcc defaults for `-falign-function` and `-falign-loops` do pad for alignment in the default tuning options. The NOPs between functions never execute so they don't cost anything except for "diluting" code density in the i-cache. – Peter Cordes Sep 27 '20 at 04:52
  • @PeterCordes by the way, I updated the question to use the Intel code (which reduces it by about 30%) and also link to the instruction page, where found. – David542 Sep 27 '20 at 06:21
  • 1
    `setbe` and so on are all `setcc` instructions. Similarly for `cmovcc` and `jcc`, it's weird to not group those mnemonics together when you're grouping all operand-sizes of `mov` together, and stuff like that. (I get that it's just because the script is simple text-processing, but just saying.) AT&T disassembly omits operand-size suffixes when they're redundant so AT&T disassembly wouldn't give you operand-size for everything even if you did want it. Also, `rep` is a *prefix* that applies to instructions like `movs` or `stos`. `rep movs` is effectively one micro-coded instruction. – Peter Cordes Sep 27 '20 at 06:35
  • @PeterCordes thanks for the feedback, yea I'll group them together, it's helpful for me too. `rep` is interesting and a bit of a mystery to me, I actually just asked a question related to it. – David542 Sep 27 '20 at 06:49

0 Answers0