RL78のローカル変数のメモリアドレスについて

こんにちは。SUZUKIです。

 

RL78/G14用のプログラムをCS+で開発中に良く分からない現象に遭遇しました。

プログラムは

void test(char a){

char b = 0;

b = a+10;

}

という簡単なものです。

この時に変数a,bをウォッチするとアドレスがそれぞれ[L:REG][H:REG]となっており、変数bの値は0のままでした。

動作する条件としては下記3つありました。

1.変数bの宣言をグローバルで行った場合

2.別の変数(使用しない)を関数内で宣言した場合

3.変数bの型をint型にした場合

これらの時は変数a,b共にアドレスが割り当てられ正常に動作しました。

これはどのような事が起きているのでしょうか。

宜しくお願い致します。

  • わわいです
    変数というのは、基本的にメモリに割り当てられます。が、
    AUTO変数で、その関数の処理内容からレジスタが空けることができる場合、レジスタに割り当てられ(ることもあり)ます
    そこらへんはお使いのツールチェインのマニュアルに書いてありますんで読んでみてください。

    一般的にメモリよりレジスタのほうがアクセスは早く、アクセスの自由度も高いため、よく使う変数はレジスタを使うほうが処理速度は早くできます
    #AUTO変数をレジスタに割当てる指定(register)もあったりしますねー

  • わわいです
    んで、もうひとつ。
    コンパイラの最適化をありにしていると、コンパイラは内容の値が使用されていない変数があれば、その変数に関わるコードを省略する場合があります。
    示されたコードでは、おそらく変数bの値が使用されないため、それが関わるコードを省略されてしまった結果だと思われます

    ここで、bの操作を省略されたくない、という場合は、コンパイラのオプションで、最適化をなしにするか、b の宣言時に volatile を追加することですね

    volatile char b=0;
  • ありがとうございます。

    volatileで宣言することで正常に動作を行いました。
    質問時のコードは簡略化しており、実際には別関数呼び出しの引数として変数bを使用していたため、volatileは必要無いという認識でした。
    引数としてではだめなのですね・・・
  • わわいです
    >質問時のコードは簡略化しており、実際には別関数呼び出しの引数として変数bを使用していたため、volatileは必要無いという認識でした。

    関数の引数にしている場合はそーゆー最適化はなされないはずです。volatileは必要ないです
    コンパイラの設定で、インフォメーションメッセージを出す設定にしておけば、そんな場合(未使用変数がある、とか、影響ない操作してるとか)にメッセージを出してくれますんで、やってみてはどうでしょう

    #余計なお世話のメッセージも山ほど出ますがw
  • わわいさん、こんにちは。NoMaYです。横から失礼します。

    SUZUKIさんが質問用にコードを簡略化する前の実際のコードで、こう何というか、ひょっとしてコンパイラのバグ?とも思われるような話になって来たような気がしたのですが、こういう話になって来たら、これは正確な状況を聞いてみた方が良くないでしょうか?

  • デバッガで参照できないというだけで、プログラムは動作するのでは?
    それならデバグ中は最適化禁止を指定すれば良いだけのことで、ソースに小細工は不要です。
  • 最初のSUZUKIさんの書き込みからは、省略された変数bをデバッガーから参照できたように読み取れます。
    実態のない変数を参照できて、中身がゼロと言うのはCS+のバグのように感じるのですが、。
  • SUZUKIさん、こんにちは。NoMaYと申します。

    もし宜しければ、以下の点について教えて頂けないでしょうか?わわいさん同様、簡略化する前の実際のコードで別関数呼び出しの引数として変数bを使用していたのであれば、volatileは必要無い筈なのだけれども、と思うからです。

    (1) コンパイラの種類(CC-RLかCA78K0Rか)とバージョン、CS+のバージョン、コンパイル時の最適化レベル

    (2) 簡略化する前の実際のコードですが、CS+でウォッチした変数のアドレス/内容に関してを一旦脇に置けば、プログラムの動作そのものはvolatileを付けなくても期待した通りに動作していた、のでしょうか?(それとも、実際のコードでプログラム自体が動作していなかったので、CS+でウォッチして変数を確認していたという状況であり、実際のコードでvolatileを付けたらプログラム自体が動作するようになった、という状況でしょうか?)

    状況によっては、以下も教えて頂けないかどうか、尋ねさせて頂くことになるかも知れません。

    (3) 簡略化する前の実際のコードで呼び出されていた別関数に引き渡された変数bの値は、その別関数の中に入ってから、その関数の引数(仮にarg_b)をvolatile宣言したグローバル変数(仮にdebug_b)に代入してdebug_bの値をCS+のウォッチで確認してみた時は、期待した通りの値になるでしょうか?(何のことだか分かり難いですね。その時には、もっと分かり易く書いてみます。)

    (4) 簡略化する前の実際の関数の全体、そこで呼び出されている関数のプロトタイプ宣言すべて、そこで使用されているマクロ定義すべて、簡略化する前の実際の関数のコンパイルリスト(CS+の設定でコンパイルされた結果のアセンブラコードをlstファイルに出力することが出来ますので、それからの抜粋となります)、をzipファイルに固めて添付して投稿して頂く事は出来ますか?

    (4') 或いは、CS+のmtpjファイル、簡略化する前の実際の関数が含まれるCソース、そのソースをコンパイルするのに必要なヘッダファイル全て、をzipファイルに固めて添付して投稿して頂く事は出来ますか?

    (4'') 更に或いは、いっそのこと、CS+のプロジェクト全体(つまり全てのソースファイルとmtpjファイル)をzipファイルに固めて添付して投稿して頂く事は出来ますか?(もちろん、上司の許可というか会社の許可が必要になるとは思いますが。)

  • こんにちは。NoMaYです。自己フォローです。

    そういえば、以前、CC-RXの最適化でIKUZOさんが困惑していたことを、今しがた思い出しました。Fujitaさんの予想の方が適切かも知れないです。

    RX631スタック領域等を保護するには?
    japan.renesasrulz.com/cafe_rene/f/forum5/4648/rx631/25189#25189
     

  • SUZUKIです。
    いろいろ立て込んでいて確認が遅れ申し訳ありません。
    みなさんありがとうございます。私自身良く分かっていないためみなさんの議論についていくのがやっとで申し訳ないです・・・
    NoMaYさんの質問について調べましたので回答させて頂きます。

    (1) CS+ for CA,CX
    *パッケージ・バージョン
    V4.00.01 [07 Jun 2017]
    *バージョン
    V5.02.00.02 [09 May 2017]
    *アセンブリ・バージョン
    3.12.10.1
    RL78,78K0Rビルド・ツールCA78K0R用プラグイン
    *バージョン
    V5.00.00.03 [30 Jun 2016]
    *アセンブリ・バージョン
    3.12.10.1
    *DLL ファイル名
    BuildToolCC78K0R.dll

    (2)実際のコードは
    void test(char a){
    char b = 0;
    b = a+10;
    R_DAC0_Set_ConversionValue(b);
    }
    となっており、変数bをDA変換値設定用関数の引数にしていました。
    R_DAC0_Set_ConversionValue関数にジャンプして値を見るとその関数内では正常な値となっていました。

    当初の質問時にはそこまで確認出来ておらず情報が漏れてしまい申し訳ありません。結論から言うと動作自体は出来ていますが、動作確認をしようとして、ウォッチ、ステップイン実行を行うと関数内で値を確認できないという状況でした。