ようこそ!JQ2RVNのブログです。
PICを使っていろいろな物を作ろうと画策中です。
× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。 PICでTNCを作るのが目標ですが・・・
PR
C言語の関数で2つ以上の返値を出したいときや、
もともとの変数を直接いじりたいときには、 ポインタを使うのが定石だと思います。 通常のC言語での使い方は・・・・ void func( int* a ) { *a=....; (この後の例では、*a++;を使います) } 呼び出しは func( &x ); となります。 しかし、CCSCの場合は、これではうまく動かないようです。 アセンブラリストを見ると次のようになっています。 まずは呼び出し方。 MOVLW 32 (32は変数xのアドレス) MOVWF 33 (33はfunc関数の引数aのアドレス) GOTO 060 (func関数の番地) (32や33、060という値は、コンパイラが自動的に変更してくれます。) 「33番地に、変数Xのアドレス(32)を入れて、func関数に飛ぶ」 となるので、参照動作(&がついた時の動作)は問題ないようです。 次に、func関数 060 MOVF 33,W 061 INCF 33,F 062 GOTO xxxx これを見ると変なことがわかります。 061は関数内の処理、a++;に相当するのですが、 それがINCF 33,Fとなって、33番地の内容を直接インクリメントしています。 はじめは32が入っていたので、1プラスされて33になるだけなので、 予期していた動作と違うことがわかると思います。 結論として、ポインタ呼び出しはCCSは使えないことになります。 さて、これでは使いにくいので、次のような方法があります。 void func( int8 &a ) { a++; } 呼び出し側は、 func( a ); この場合のアセンブラリストは・・・ 呼び出し側:何も記載がない(呼び出す直前のプログラムメモリは0C3) 関数側: 0C4 INCF 32,F つまり、コンパイラは関数のコールやジャンプなしに、 直接0C4番地にインクリメント命令を出しています。 なるほどといえば、なるほどな処理ですね。 もし、2か所以上から関数の呼び出しをしている場合はどうなるか? 064 INCF 36,F 0C4 INCF 32,F というように、同じ処理が2つ書かれます。 なんてことはない、インライン展開をしてるわけですね。 インライン展開にはソースの可読性もよくなり、 ポインタを意識せずとも、関数を使うことができます。 しかし、必然的にプログラムメモリの使用量は増えるので、 複雑な処理を、何か所からかコールするという場合には不適です。 その場合は、グローバル変数を用意しておいて、 そこに値を書き込んでいく処理が必要になります。 なお、MPLAB Cの場合はポインタ変数が使えますから、 最初の例のままでOKです。 |
カレンダー
プロフィール
コールサイン:
JQ2RVN
性別:
男性
自己紹介:
PICの開発を勉強中です。
目標はPICTNCの高性能版を作ること。 まずは、本家を解析しています。
カテゴリー
最新記事
最新コメント
[04/23 Eolande]
[04/16 太田和巳(JF2UJG)]
[09/10 je7ifp]
[08/06 JQ2RVN]
[08/03 OVC]
最新トラックバック
ブログ内検索
最古記事
(05/18)
(05/19)
(05/19)
(05/20)
(05/21)
アクセス解析
|