やまものブログ

メモ書きブログです (^_^;A

ARM アセンブラ C 関数コール

main() から関数 kakeruni() をコールする C ソースをコンパイルしてアセンブラを観察してみました。

まず、C ソースは下記の通りです。
イメージ 1

このコンパイル結果のアセンブラです。
イメージ 2

main() および kakeruni() ともに数字で分類したような処理内容になっているようです。

① FP 等の PUSH、引数(R0,R1,...)の保存(ストア)
オペランド値のレジスタ書込み(ロード)
③ 演算処理、結果のレジスタ書込み(R0)
④ SP 設定とPOP、ブランチ(リターン)


main()  kakeruni()  をコールするので、LR (Link Register, R14) と FP (Frame Pointer, R11) をPUSHで保存しますが、kakeruni() はコールする関数も無いので FP しか PUSH しません。

これに関係しているのか、POP してブランチで戻る際の処理が、main()  では、

pop     {fp, pc}


ですが、kakeruni() では下記のようになっています。

ldmfd   sp!, {fp}
bx      lr


main() のように pop で PC (Program Counter, R15) を PUSH で保存しておいた LR に上書きしてする方式はすっきりしているように思えます。kakeruni() のように ldmfdpopと等価) と bx に分けるのは何かメリットがあるのでしょうかね…


最後に念のためコンパイラツールのバージョン情報です。
$ arm-xilinx-linux-gnueabi-objdump --version
GNU objdump (Sourcery CodeBench Lite 2013.05-40) 2.23.52.20130219