gcc Ver2.9 でSH-2の開発をしています。
通常に関数を作成し、引数を渡しているのですが、引数が渡らないという現象が起きています。
現象は、
1.引数はポインタではなく値渡しである
2.引数の値が0の時だけ正しく渡らない。値が0以外の時は正常にわたる
3.引数の型は一致している
4.引数は複数あるが、後半のいくつかがだめ(何個とまでは詳しく調べていません)
5.ある特定の関数の特定の呼び出しのみがだめで全てだめというわけではない
6.コンパイルオプションに -m2 をつけるとだめだが、-m1 オプションだと問題ない
7.最適化オプションをなくしても同じだった
といった状況です。
上記5からある特定の記述方法とか順序になるとだめになるのではないかといろいろ試してみたのですが見つけられません。6から記述方法に誤りがあるとも考えにくい状況です。コンパイラのバグといって片付けていいものなのかどうかです。どなたか同じような経験をされた方はいらっしゃいませんか。また関数呼び出しの場合、コンパイラがどうやって引数を渡すかご教授願えませんか。
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
イミディエイト値の0だけで発生する現象のようですね。
0Lや0Uでも同じ現象でしょうか?
イミディエイトな0だけが問題を起こすならint ZERO = 0;のようなグローバル変数を定義して、0の代わりに使うという手も…
ご意見ありがとうございます。
残念ながらイミディエイト値の0だけで発生するわけではありません。
変数であってもその値が0とコンパイル時にわかる場合はだめなようです。
したがってローカル変数でint ZERO = 0;のように定義してもだめです。
しかし仰るようにグローバル変数でint ZERO = 0;のように定義すればコンパイル時にその値が0であるかどうかはわかりませんのでうまく回避できるようです。
しかし調子に乗って、const int ZERO = 0;などとやると変数の値が固定されてしまうのでコンパイラに0であることがバレて(笑)だめになってしまいます。
一応、その他の回避方法を試行錯誤で調べましたので書いておきます。但しコンパイラそのものを解析したわけではありませんので絶対にOKという保証はありません。
1.引数の数を4個以下にする。
2.引数リストの中にコンパイル時点で0になる計算式を含めない
3.0の引数は、引数リストの先頭に持ってくる
とりあえずこれで問題は起きてないみたいです。
No.2
- 回答日時:
現在スタックへのプッシュ・ポップで引数を渡すコンパイラというのはほとんど存在しないでしょう。
効率が悪すぎ、関数呼び出しの度に大きなオーバーヘッドになります。
SH-2のアーキテクチャを良く知らないで、以下は一般論です。
1.レジスタが豊富で引数用レジスタが用意できる場合(RISCに多い)
SPARCなどで採用されている方法です。
レジスタのうちの10~20個程度を引数要に割り当てます(引数がそれ以上の場合は2の方法を併用)。
更に下位の関数を呼び出す場合はスタックに退避し、関数から戻ったときにレジスタに復帰します。
下位関数の呼び出しが無ければスタックへのアクセスが発生しないため、非常に高速です。
2.ベースポインタを利用する(CISCに多い)
スタック上の引数に対してベースポインタからの相対アドレッシングで直接アクセスします。
ベースポインタが用意されていないCPUでは汎用アドレスレジスタを流用します。
稀にスタックポインタをベースポインタとして利用することもあるようです。
3.引数領域を別途用意する
スタックが無く、レジスタに余裕が無い場合にのみ利用されます。
汎用コンピュータのCコンパイラで見られます。
スタックを利用する場合でもPUSH・POP(PULL)系の命令が使われることはほとんどありません。
1ワードを超えるデータ長の引数を扱うときに効率が悪くなるため、ベースポインタからの相対アドレスに対してMOVE系の命令を使うことが多いでしょう。
gccなら-Sオプションでコンパイルすればアセンブラ展開形が確認できると思います。
詳しい解説をありがとうございます。
デバッガで逆アセンブルをかけて解読しました。
結論は、コンパイラのバグのようです。
SH2は汎用レジスタの数が比較的少ないため、引数はレジスタとスタックで渡されています。
スタックはレジスタの相対アドレッシングで参照しています。問題の引数は通常、レジスタにイミディエイトで値をセットし、それをスタックにセットするという手順で渡されています。
ところが、問題の箇所で引数が0の場合、イミディエイトで値をセットする代わりに、MACレジスタの値を転送しています。
このMACレジスタがクリアされていれば問題ないわけですがそれは行われていません。
デバッガでクリアされない値が渡っていくことを確認しました。
コードで書くとこんな具合です。
(XXXXには相対アドレスが入ります)
正常時:
MOV #0, R1
MOV.L R1, @(XXXX,R15) ;これで引数セット
NG時:
STS MACL, R1
MOV.L R1, @(XXXX,R15) ;これで引数セット
残る問題は対策です。コンパイラのbugfixを待つのは正攻法ですが、そんな悠長なことは言ってられません。引数に0を使わないというのも無理があるし、引数0があるたびにMACレジスタクリアの命令を挿入するのも面倒だし弱っています。どういう記述をするとそうなるのかという法則を見出すしかないのでしょうか。
No.1
- 回答日時:
引数がいくつかっていうのが気になりますが、
0というのは定数リテラルで渡してるんでしょうか?
それともConst定数でしょうか?それとも変数に格納したもので?
引数を渡すときは、最終的にスタック領域にプッシュして関数ポインタにジャンプしてスタックからポップという動きになるのはどのコンパイラでも一緒ですからねえ。。。
単なるコンパイラのバグと片付けてしまっていいと思いますよ。
どうしても気になるんでしたら、逆アセンブルをかけてアセンブラにしてトレースしていけば詳しい動きがわかりますよ。(結果は同じなんですけどね^^;)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- JavaScript カラーミーショップのsectionループ内で、[引数][戻り値]ありの関数的な処理を行いたいです。 1 2022/05/07 19:39
- C言語・C++・C# C言語初心者です、、、お助けください 2 2023/03/14 20:08
- UNIX・Linux Linuxについて2つ質問したいです。 ① シェルスクリプト名をawk1.shとして、指定されたデー 1 2023/02/03 03:49
- Gmail おすすめメーラー 1 2022/11/23 20:25
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- ライブ・コンサート・クラブ この件についてどう思うか教えてください とあるイベントチケットに行きたく、Twitterで譲渡してく 3 2023/04/08 23:37
- 大学受験 合同式 2 2022/08/19 13:12
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
gccでスタックサイズを変更する...
-
エラー?メッセージ
-
printf / sprintf のスタック消...
-
最大スタックサイズを大きくす...
-
VB.netでDLLを読み込んで実行す...
-
プログラムの規模を表す単位「k...
-
パソコンでインターネット接続...
-
ubuntuで デイスク/deb/loopと...
-
Macと iPadの違いについて 今現...
-
ワープロ検定の勉強法について。
-
エクセルのHLOOKUP関数の検索範...
-
ネットワークアイコンが黄色三...
-
タイピング速度を上げる方法に...
-
RS-FF回路について
-
タイピングの癖
-
Excel VBA マクロ処理 リンク先...
-
ブラインドタッチ、苦手なんで...
-
ブロック化因数(ブロッキング...
-
タイピングを極めたい
-
タッチタイピング
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VB.netでDLLを読み込んで実行す...
-
最大スタックサイズを大きくす...
-
エラー?メッセージ
-
Ethernetヘッダの取得 NDIS
-
GCCで関数の引数が渡らない
-
printf / sprintf のスタック消...
-
スタックフレームの消滅
-
H8マイコン スタック領域に...
-
pthreadのスタックサイズ設定取...
-
_CRTIMPの意味は?
-
スタックを用いて整数配列を入...
-
再帰処理を非再帰処理に書き換...
-
VC++でプログラムから現在のス...
-
cloneのスタック管理
-
マス目上の移動のアルゴリズム
-
gccでスタックサイズを変更する...
-
OCXからのコールバックを繰り返...
-
コンパイラオプション
-
VC++6.0 Stack Overflow !!
-
スタック領域変更
おすすめ情報