[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[WitchTech 00254] Re: LSI-CforWitch の関数ポインタ
長久です。
2000/08/08 16:24:17 +0900にYasuo OHNO <y_ohno@geocities.co.jp>さんに頂いた
「[WitchTech 00252] Re: LSI-CforWitch の関数ポインタ」への返事です。
>tiny は CS == DS で code + data で 64k に収まるメモリーモデルで
>small は CS != DS で code 64K、data 64K のメモリーモデルですよね。
>small では code は 一つのセグメントに納められているはずですから、
>関数の call は near で、return も nearで生成されるはずです。
ふむふむ、という事は
CS-DS,SS間問題をDS-SS間問題と同じ認識だった点が私の心得違いだった様です。
関数ポインタは、内部的に変数ポインタとは区別して扱われるので、
code配置に関してのみセグメントを意識してやれば良いと。
で、smallモデルの場合、codeセグメントは1個しかないので、
far宣言はいらないって事ですね。
で、DS-SS問題は、dataセグメントが2個になるんで、
セグメント間を跨いだ参照にはfar使えと。
そんな感じですかね。
ついでに考察。
disp.hなんか見ると、BIOS_INLINE時ですが
void near sprite_set_data
(unsigned sprite_no, unsigned sprite_count, void far *data_p);
みたいに記述があるので、
非BIOS_INLINE時も準拠してればいいなあとか期待すると、
(service???()とか、もうついてけません(T_T)
BIOS呼出関数の引数のポインタはfarっとけって事なんでしょうが、
この場合、symbolがデフォルトnearで作られるLSI-CforWitchの場合、
1:DS領域(ヒープ)を指すようにして、
セグメント指定をレジスタ状態おまかせにして、やり過ごす。
static使ったりグローバル使ったりして乗り切る。
2:一旦farポインタに代入して、そいつを渡す。
代入時って、ちゃんとキャストされてんだろうなと祈る。
ローカル変数で処理可。
の何れかを明示的に選べって事なんですよね?
>なので、長久さんが例にあげていた関数ポインタから呼ばれる関数
>
>char t1(int no){
> return no + 1;
>}
>
>は near の関数になっているはずだと思いますよ(^_^;)
>これを far 呼び出しするとスタックが壊れて暴走するかと思います。
この辺、コンセンサスが取れてないようなので、
以下にfarで暴走するコードを書いときます。
文法上タブンあってます(^^;
----------
#include <sys/bios.h>
#include <stdio.h>
char (far *tmp_func)(int no);
char far t1(int no);
char far t2(int no);
void main() {
static char str[32];
text_screen_init();
text_put_string(0, 0, "start");
tmp_func = t1;
sprintf(str, "%d", (*tmp_func)(1));
text_put_string(0, 1, str);
tmp_func = t2;
sprintf(str, "%d", (*tmp_func)(1));
text_put_string(0, 2, str);
while(1)
if(key_press_check() == KEY_START)
break;
}
char far t1(int no) {
return no + 1;
}
char far t2(int no) {
return no + 2;
}
----------
でもまあ、64KB越えるコードってそうないだろうと言う事にしときましょう。
そんときは少なくともLSI-Cとオサラバだし(^^;
神楽坂酔っ払い研究所所長
長久 勝(ながく まさる)
mailto:mnagaku@cap.bekkoame.ne.jp
http://www.bekkoame.ne.jp/~mnagaku/
ML Archives