忍者ブログ
ようこそ!JQ2RVNのブログです。 PICを使っていろいろな物を作ろうと画策中です。
[12] [11] [10] [9] [8] [7] [6] [5] [4] [3] [2]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

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です。
PR

コメント


コメントフォーム
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード
  Vodafone絵文字 i-mode絵文字 Ezweb絵文字


トラックバック
この記事にトラックバックする:


忍者ブログ [PR]
カレンダー
09 2017/10 11
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
プロフィール
コールサイン:
JQ2RVN
性別:
男性
自己紹介:
PICの開発を勉強中です。
目標はPICTNCの高性能版を作ること。
まずは、本家を解析しています。
最新コメント
[04/23 Eolande]
[04/16 太田和巳(JF2UJG)]
[09/10 je7ifp]
[08/06 JQ2RVN]
[08/03 OVC]
最新トラックバック
バーコード
ブログ内検索
アクセス解析