みなさんにはアプリのデバッグで、結局アセンブリという自分には理解不能な壁を見るだけになった経験があったでしょう。もしくは、なぜUIKitがこのような挙動を示すのかを理解するために、UIKitのメソッドのソードコードをみたくなったこともあるかもしれません。このトークでは、我々のような普通の開発者でもアセンブリを深く学ぶことによって、バグを見つけ出したり、システムフレームワークのリバースエンジニアリングを行ったり、自身のコードをより深く理解することができることをお見せします。
5歳
大学で電気光学を勉強
2005年Cocoaプログラミングはじめ
仕事はiOSを教えること
趣味はレトロパソコンを集めること
15年前に日本に住んでいました
アセンブリを語るのに20分では語れません
ほとんどのひとが怖がっているとおもいます。怖がらなくていいということ、そして実務的ヒント
デバッグで知っておくことが助けになると思います
アセンブリはどんな言語?
マシンコードはバイナリ、アセンブリは一番近い、そして人間が読めるプログラム。
コンパイルすると、言語が違っても、バイナリコードに成る。アセンブリで人間が読めるので知識として分かるように成る
用語を買うニンしましょう 確認
64ビットの値が入る
どのCPUかで違う
汎用レジスタも特定関数向けのようなものもある
CPUの中に入っていて、とても早い
変数と考える事もできる
次の用語
単純な名前で命令。ニーモニックを使ってCPUの命令を参照する
mov 値を別のレジスタに動かす
add 2つの数字を足し合わせる
sub 引く
cmp 比較する、ある意味引き算。
jne jump not equal 最後のオペレーション結果でどこかに飛ばす、ifみたいな
nop なにもしない、遅延を起こす
call ファンクションよびだし
pop スタックのポップ
ret リターン、callのところに戻る
コードごとにオペランドが続く
mov r8 0x42 は16進数0x42をr8に動かす
最初に命令、intelとAT&Tがあるが今日はintelシンタックス。
最初のオペランドは宛先、そしてソースの順
呼び出し規約
特定レジスタに入れ込んで、addファンクションが探しに行く
どのレジスタでどのargを戻すのかを見ていく
callingコンベンションはCPUなどによってかわる
有名なのはx86、64ビットですと
このリストはおぼえておいたほうが良いですデバッグの助けになります。
同じコードだが
最初にAddファンクションが呼ばれる。
適切なレジストリに入れる
最初の2 はrdiに
rdiから2をとりだし、raiから3を取り出し、5をraxにいれる
return
コントロールがメインファンクションに戻る。
結果を取りに行く
以上が呼び出し規約
同じ簡単な関数で2つの引数で結果を戻す
Swiftでも同じような見栄え
コンパイルすると
最適化されていない。
最適化化すると見栄えが変わる。
9行になっているが1行ずつ分けていくとよく分かる
最初の2行、関数のプロローグ、いくつかのものが設定され関数本文で実行できるようにする
つぎに引数をレジスタから確保する
rdi、rsiからスタックに入れる
rsiに
加算
結果を格納
戻る・
どう役立てるか。
最もあるのはデバッギングです。
クラッシュするとアセンブリコードがたくさん出てきます。
全く意味がわからないと思ったりしますが、
有用な情報を得られたりします。
po $rdi
といれればいい
もっと複雑な場合
touch beganをしりたい
b -[UIResponder touchesBegan:withEvent:]
どのオブジェクトでこれが起きたのか。
レジスターで呼び出し規約を使える。
Objecitve-Cは動的DispatchしているのでObjective-C Message Send
rdiでプリントすることが出来る
po $rdi
UITableViewCellContentViewだということが分かる
po (SEL)$rsi
レシーバーとセレクタの引数は1つ目が3つめになるので po (id)$rdx
LLDBをObjective-Cモードで使える
コマンドを使ってエイリアスを作れる
もうひとつ、役立つツール
擬似コードを作りアセンブラが何を行っているか分かる。Disassembly、リバースエンジニアリング、どのように実装されているか、Hopperが役に立つ、お金を出したぶんの価値が得られます。
もっとしりたけれ
今の内容とより多くの情報を得ることが出来ます。
チュートリアルもあります。
スライドです
少しは理解していただけたでしょうか、もっと学びたいと思っていただけたでしょうか。
ご清聴ありがとうございます。