こんにちは。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共にアドレスが割り当てられ正常に動作しました。
これはどのような事が起きているのでしょうか。
宜しくお願い致します。
SUZUKIさん、こんにちは。NoMaYです。すみません。夜遅くなるどころか日付まで変わってしまいました。CA78K0RとCC-RLでコンパイラが生成するコードを調べてみました。試したプロジェクトは以下のzipファイルに固めてあります。ただ、書いてみて思ったのですが、もっと分かり易く書き直さないと駄目な気がします。もう少し、書き方を考えてみようと思います。Issue_20171214.zip具体的には以下のソースコードに対して2×3=6つの条件でコンパイルして、コンパイルリストを出力させ、変数bへの代入がどうなっているかアセンブラコードを調べました。
void test(char a){ /* volatile */ char b = 0; b = a+10; R_DAC0_Set_ConversionValue(b);}
(1) CA78K0R V1.72(2) CC-RL V1.02 (当方特有の事情で最新版では無いです)(A) 最適化なし(B) プロジェクト作成時のデフォルトの最適化(C) プロジェクト作成時のデフォルトの最適化で変数bをvolatile宣言今回の件は(1-B)に該当するのですが、わわいさんがアドバイスしている通り、最適化のため変数への値の代入がなされなかった、ということです。ただ、ちょっと紛らわしいことに、もう少しCA78K0Rが賢ければ多分なされなかったと思われる「0を代入する」ことは行われており、それに対して「a+10を代入する」ことだけが行われなくなっていたので、ということでした。(ちなみに、CC-RLでは「0を代入する」ことも行われなくなっていました。)(1) CS+ for CA,CX V4.00.01 + CA78K0R V1.72(1-A) 最適化なし ⇒ 0(00H)や変数a+10(0AH)を変数bへ代入している
760 760 ; line 83 : void test(char a){ 761 761 00012 _test: 763 763 00012 C7 push hl ;[INF] 1, 1 764 764 00013 C1 push ax (補)引数aをスタックに移す ;[INF] 1, 1 765 765 00014 C1 push ax (補)変数bの領域をスタック上に確保する ;[INF] 1, 1 766 766 00015 FBF8FF movw hl,sp ;[INF] 3, 1 768 768 ; line 84 : /* volatile */ char b = 0; 770 770 00018 CC0100 mov [hl+1],#00H ; b,0 ;[INF] 3, 1 771 771 ; line 85 : b = a+10; 773 773 0001B 8C02 mov a,[hl+2] ; a ;[INF] 2, 1 774 774 0001D 0C0A add a,#0AH ; 10 ;[INF] 2, 1 775 775 0001F 9C01 mov [hl+1],a ; b ;[INF] 2, 1 776 776 ; line 86 : R_DAC0_Set_ConversionValue(b); 778 778 00021 318E shrw ax,8 (補)AレジスタをAXレジスタ(引数)に移す ;[INF] 2, 1 779 779 00023 RFC000000 call !!_R_DAC0_Set_ConversionValue ;[INF] 4, 3 780 780 ; line 87 : } 783 783 00027 1004 addw sp,#04H ;[INF] 2, 1 784 784 00029 C6 pop hl ;[INF] 1, 1 785 785 0002A D7 ret ;[INF] 1, 6
(1-B) プロジェクト作成時のデフォルトの最適化 ⇒ 0(00H)を変数bへ代入しているが、変数a+10(0AH)を変数bへ代入していない
759 759 ; line 83 : void test(char a){ 760 760 00012 _test: 762 762 00012 C7 push hl ;[INF] 1, 1 763 763 00013 16 movw hl,ax ;[INF] 1, 1 765 765 ; line 84 : /* volatile */ char b = 0; 767 767 00014 5700 mov h,#00H ; 0 ;[INF] 2, 1 768 768 ; line 85 : b = a+10; 770 770 00016 66 mov a,l ;[INF] 1, 1 771 771 00017 0C0A add a,#0AH ; 10 ;[INF] 2, 1 772 772 ; line 86 : R_DAC0_Set_ConversionValue(b); 774 774 00019 318E shrw ax,8 (補)AレジスタをAXレジスタ(引数)に移す ;[INF] 2, 1 775 775 0001B RFC000000 call !!_R_DAC0_Set_ConversionValue ;[INF] 4, 3 776 776 ; line 87 : } 779 779 0001F C6 pop hl ;[INF] 1, 1 780 780 00020 D7 ret ;[INF] 1, 6
(1-C) プロジェクト作成時のデフォルトの最適化で変数bをvolatile宣言 ⇒ 0(00H)や変数a+10(0AH)を変数bへ代入している
759 759 ; line 83 : void test(char a){ 760 760 00012 _test: 762 762 00012 C7 push hl ;[INF] 1, 1 763 763 00013 C1 push ax (補)引数aをスタックに移す ;[INF] 1, 1 764 764 00014 C1 push ax (補)変数bの領域をスタック上に確保する ;[INF] 1, 1 765 765 00015 FBF8FF movw hl,sp ;[INF] 3, 1 767 767 ; line 84 : volatile char b = 0; 769 769 00018 CC0100 mov [hl+1],#00H ; b,0 ;[INF] 3, 1 770 770 ; line 85 : b = a+10; 772 772 0001B 8C02 mov a,[hl+2] ; a ;[INF] 2, 1 773 773 0001D 0C0A add a,#0AH ; 10 ;[INF] 2, 1 774 774 0001F 9C01 mov [hl+1],a ; b ;[INF] 2, 1 775 775 ; line 86 : R_DAC0_Set_ConversionValue(b); 777 777 00021 8C01 mov a,[hl+1] ; b ;[INF] 2, 1 778 778 00023 318E shrw ax,8 (補)AレジスタをAXレジスタ(引数)に移す ;[INF] 2, 1 779 779 00025 RFC000000 call !!_R_DAC0_Set_ConversionValue ;[INF] 4, 3 780 780 ; line 87 : } 783 783 00029 1004 addw sp,#04H ;[INF] 2, 1 784 784 0002B C6 pop hl ;[INF] 1, 1 785 785 0002C D7 ret ;[INF] 1, 6
(2) CS+ for CC V6.00.00 + CC-RL V1.02(2-A) 最適化なし ⇒ 0(0x00)や変数a+10(0x0000A)を変数bへ代入している
00000009 121 _test:00000009 122 .STACK _test = 600000009 127 ;*** 84 : void test(char a){00000009 C7 129 push hl (補)引数aと変数bの領域をスタック上に確保する0000000A 9801 130 mov [sp+0x01], a (補)引数aをスタックに移す0000000C 131 ;*** 85 : /* volatile */ char b = 0;0000000C C80000 133 mov [sp+0x00], #0x000000000F 135 ;*** 86 : b = a+10;0000000F 8801 137 mov a, [sp+0x01]00000011 318E 138 shrw ax, 8+0x00000 (補)AレジスタをAXレジスタ(作業用)に移す00000013 040A00 139 addw ax, #0x000A00000016 60 140 mov a, x00000017 9800 141 mov [sp+0x00], a00000019 143 ;*** 87 : R_DAC0_Set_ConversionValue(b);00000019 8800 145 mov a, [sp+0x00]0000001B FC000000 146 call !!_R_DAC0_Set_ConversionValue0000001F C6 147 pop hl00000020 D7 148 ret00000021 149 ;*** 88 : }
(2-B) プロジェクト作成時のデフォルトの最適化 ⇒ 0(0x00)も変数a+10(0x0A)も変数bへ代入していない
00000009 113 _test:00000009 114 .STACK _test = 400000009 119 ;*** 84 : void test(char a){00000009 0C0A 121 add a, #0x0A0000000B 122 ;*** 85 : /* volatile */ char b = 0;0000000B 123 ;*** 86 : b = a+10;0000000B 124 ;*** 87 : R_DAC0_Set_ConversionValue(b);0000000B EC000000 126 br !!_R_DAC0_Set_ConversionValue0000000F 127 ;*** 88 : }
(2-C) プロジェクト作成時のデフォルトの最適化で変数bをvolatile宣言 ⇒ 0(0x00)や変数a+10(0AH)を変数bへ代入している
00000009 113 _test:00000009 114 .STACK _test = 600000009 119 ;*** 84 : void test(char a){00000009 C7 121 push hl (補)変数bの領域をスタック上に確保する0000000A 122 ;*** 85 : volatile char b = 0;0000000A C80000 124 mov [sp+0x00], #0x000000000D 125 ;*** 86 : b = a+10;0000000D 0C0A 127 add a, #0x0A0000000F 9800 128 mov [sp+0x00], a00000011 129 ;*** 87 : R_DAC0_Set_ConversionValue(b);00000011 8800 131 mov a, [sp+0x00]00000013 FC000000 132 call !!_R_DAC0_Set_ConversionValue00000017 C6 133 pop hl00000018 D7 134 ret00000019 135 ;*** 88 : }