出現頻度の高いアセンブラ命令を調べてみる。
x86-64のアセンブラ命令数はすでに1000前後あるみたいです。ただそんな数の命令をいちいち覚えてられないだろうという話で、実際よくみるのはほんの20命令くらい、特別なことをしないならばだいたい100命令くらい覚えていれば問題ないんじゃないの? という感じがします。
「たのしいバイナリの歩き方」の1章でもそんな話題に少し触れています。
まぁそもそも使用しているプログラミング言語の予約語だって、全部覚えてから使い始めるわけじゃないですし。でも、じゃあどの命令を覚えておけばいいんだろう、という疑問が。
そこで、適当なプログラムを集めて逆アセンブルし、出現するアセンブラ命令をカウントしていけばいいんじゃないかと。たくさん出現するアセンブラ命令ほど覚えておいた方がよい、ほとんど出てこないものはとりあえずスルーしておこう、みたいな。
ではさっそく。まずC:\Program Files以下にあるEXEファイルを集めて、テキストセクション(.text)を逆アセンブル。その結果から命令(opecode)だけをカウントしていく。C:\Program Files以下にあるEXEファイルはひとそれぞれだと思いますが、ぼくの環境の結果はこんな感じでした。
01. mov 382077 11. ret 17117 21. popa 3850 02. push 294472 12. or 15490 22. shl 3826 03. call 141420 13. dec 12280 23. outsb 3801 04. add 113244 14. movzx 11270 24. ja 3599 05. int3 84545 15. jc 10458 25. insb 3138 06. cmp 83456 16. retn 10403 26. sbb 3059 07. lea 82858 17. imul 7870 27. jnl 2916 08. pop 72727 18. jnc 7311 28. arpl 2796 09. jz 62306 19. adc 6151 29. sar 2762 0a. test 45390 1a. shr 5231 2a. jg 2354 0b. jmp 44788 1b. jl 4841 2b. jo 2345 0c. jnz 44400 1c. outsv 4832 2c. js 2164 0d. xor 36666 1d. leave 4772 2d. mul 2040 0e. and 28319 1e. jna 4497 2e. neg 2003 0f. sub 24726 1f. nop 4252 2f. jns 1580 10. inc 21494 20. jng 4146 30. cwd 1489
わりと見慣れた命令が並んでるかなーと思います。とくに左側、トップ0x10はとても身近な感じです。
出現した各命令(上位100位まで)のカウント数をグラフにもしてみました。
ごく一部の命令はすごく出現するのに対し、まったく出現しない命令も多いですね。これは100位までを載せているので、だいたい25位以降はあまり出現しない感じです。となると、実際よくみるのは20命令くらいだなーという感覚はなんとなく当たってたのかも。
個人的な印象としてはadd命令が少し多い気がしました。これは0x00スタートの命令なので、ゼロクリアされた領域を逆アセンブルしてしまい増えているのかなーと。int3も似た印象ですね。nopはもっと多いと思ってましたが、意外と少なかったです。
こんな感じでアセンブラを眺めてみるのも面白いかもしれません。ちなみに5年前にも同じようなことやってますw