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共にアドレスが割り当てられ正常に動作しました。

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

宜しくお願い致します。

Parents
  • 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ファイルに固めて添付して投稿して頂く事は出来ますか?(もちろん、上司の許可というか会社の許可が必要になるとは思いますが。)

  • 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関数にジャンプして値を見るとその関数内では正常な値となっていました。

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

    当初の質問時にはそこまで確認出来ておらず情報が漏れてしまい申し訳ありません。結論から言うと動作自体は出来ていますが、動作確認をしようとして、ウォッチ、ステップイン実行を行うと関数内で値を確認できないという状況でした。
Children
  • わわいです
    もひとつもひとつですが、、
    最適化ありの設定でコンパイルすると、Cのソース行と機械語の対応が1対1ではなくなってきたりします。
    前に言ったように省略されるコードもあり、複数のコードが単一ないしは不可分の一連のコードに展開されたり、はたまた命令の実行順序が入れ替えられたりします。
    そのため、最適化有りのコードをソースデバッグすると、ステップの順序があちこち飛んだり、到達しないコードが出てきたりします。また、変数モニタも最適化のため値の代入がなされなかったり、代入のタイミングがずれたりなんかもします。

    ということで、そういう場合には、コンパイラの最適化を、「なし」あるいは「デバッグ用」にしてコンパイルすると、きちんと追いかけられるようになります