質問: 自分は将来アセンブリも読めるようになりたいので色々勉強をしているのですがよく要領がつかめません。というのは、コンパイラが吐き出したアセンブリコードはCPUを中心とした機械側(コンピュータアーキテクチャ)にとっては飽くまで仕様みたいなものであって、実際は全然違う(ディテール部分はマシンに因る)ということなんでしょうか? このサイトで色々いじってはみるのですが、どうも挙動が読めません。(特にIPがどこから出てきたのかわかりません...) もしアセンブリコードが人間側の仕様みたいなものだとするのなら、レジスタやらメモリやらは人間側がそういう風にいじったことにしただけ、というような気がします。 自分が知りたいのは、だとするとCPUの特性を知り尽くさないとあまりパフォーマンスが出せないことになるのでは?ということや、アセンブリを書くことに意味があるのか?といったことについてです。さらにアセンブルした機械語も、実際のRAM上では正しく値がセットされていない、ということになりませんか?だとするとデバッガやシミュレータとはなんだったのか?という気がしてしまいます。本当にレジスタの値は読めているんでしょうか? どうも透過性という概念と何か関係がありそうなのですが... あまりにも分からないことだらけです。よろしくお願いいたします。 追記 たくさん回答してくださって皆さんありがとうございました。 とても参考になりました。言われてみれば確かにCPUごとにアセンブリが対応していることを失念しておりました。自分の中では結局のところ現代のCPUではとても理解が及ばないかもしれない、ということを思いました。 レイヤーの話もありましたが、自分は精々アセンブリレベルのことが知りたいだけだったので、なんとなく腑に落ちました。
回答: ちょっと何を言いたいのかが伝わって来てないんですが... IPはPC(プログラムカウンタ)ですね。RAM上の現在の実行している処理のアドレスが入ってます。 IPのアドレスにある値を読めば命令が分かります。命令がわかれば全体の長さも分かるので、次実行するべきアドレスは全体の長さを足せば算出できますよね? 紹介されてるサイトって結構親切ですね。 行毎に青く塗ってあるのでわかりやすいです。 動作を1Hzに変えたら、もっと分かりやすくなると思いますよ。 例えば、RAMの1行目の末尾の`06`が`start:`の次の行にある`MOV`ですね。 3行目の後ろの方にある`27`が`JNZ`で`.loop (1F)`に飛ばしてるから`27 1F`ってなってますね。 IPの値がそのように変わって行くのが分かると思います。 アセンブラでは、メモリ上のどのアドレスをどうするとか、レジスタをどうするとかってレベルの話になります。 命令した値が命令したレジスタに入ります。それが所望の値でなかったら書いた人のほうが間違ってるんですね。 一応エラッタがあって所望の動作にならないという事はありますが、市販されているレベルの製品ではレアケースですね。有名所ではPentium時代の電卓ですかね。w CPUの仕組みを知り尽くさないと...というのは、一からアセンブラで記述するんならそうでしょうね。 でもアセンブラは、部分的にコンパイラが出す結果と違うcodeにしたかったり、アセンブラで書くしかない(レジスタの値使いたいとか...)という所に、部分的に用いることが多いかと思います。 なので、基本的に、コンパイラに任せた方が良いバイナリが出力できます。 また、アセンブラはCPU毎に変わるので、現在どんな命令系のCPU使ってるかによってかなり変わります。`x86`とか`AMD64`とか聞いたことがありますよね?それです。 なので、動作させたい命令系に合わせてコンパイラは変えてあげないとダメです。Windows用にコンパイルしたバイナリをiPhoneやAndroidに持って行っても動きませんよね? 明確な目的が無いんだけど、勉強したいというなら簡単なもののアセンブラを勉強することをオススメします。`x86`は、読めないことは無いけど難しかったような記憶があります。