[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[WitchTech 00028] Re:



樋口です。

フォローになればいいですが。
これ、川俣さん達がおっしゃっている DS!=SS 問題ですね。 

>は、普通に考えたらまったく同じ挙動を示すはずですが、BIOS_INLINEマクロ
>が定義されると後者は何も表示しなくなりました。
>こういうときにコンパイラはどのようなコードを生成しているのでしょうか?
>文字列リテラルやchar配列の実体はどこに置かれるのでしょうか???

秘密は include/sys/service.h と include/sys/text.h にあります。
BIOS_INLINE を定義しない場合、text_put_string()は

int near text_put_string(int x, int y, char far *str);
                                       ^^^^^^^^^^^^^^
ですので、strは farポインタとなり、セグメント値も含めて渡されています。
ちょっと乱暴ですが68000なんかでいうと32bit(24bit)アドレスで渡されてい
ると思ってイイです。

これがBIOS_INLINEを定義すると、
下のように割りこみサービスに展開されるようです。
#define text_put_string(x, y, str) \
	servicewp(INT_TEXT, TEXT_PUT_STRING, MK_WORD(x,y), str)

#define servicewp(vector, ah, bx, dx) \
	_asm_intwp("\tint\t" _q_(__eval__(vector)), (ah)<<8, bx, _DUMMY_, dx)
                                                                         ^^^^^
で秘密は^^^^の部分、strのアドレスはDXレジスタに渡されるのですが、ここで
セグメント値の受け渡しがありません。 つまり20Bitのアドレスのうち下位16ビット
しか渡していないことになります。dxレジスタが扱うデフォルトセグメント
レジスタはDSなので、サービスルーチンで明示的にオーバーライドしない限り
DSレジスタが暗黙のうちに使用されるのですが、このときのDSはDGROUP、つま
りram0を示しているのではのではないでしょうか?

通常文字列リテラルはDATAセクションに置かれます。DATAはBSSと共にDGROUPに属し
ていますのでDSがDGROUPを示していればDXのみでアドレスを表現できます。
しかし、この場合bufをスタックに取っているのでbufのアドレスはSTACKセクション
に取られます。STACKセクションはDGROUPに属さず、SWANのIRAMにあるようですので
DSを使ってしまうと、別のアドレスを示すことになってしまいます。この場合の
セグメント値はStackSegmentRegsister SSの値を渡してやらなければなりません。
 
すごくイメージがつかみにくいと思いますが 68000でa6 link命令を使っているのに
a6にフレームポインタ設定するの忘れてとんでもないアドレスになっているって
感じ……かなぁ。

取り敢えず
  foo() {
       static char buf[BUFSIZE];

       .......
  }

ってやって、BSSに追い出せば動くと思うんですけど……。でもRAMが勿体ないよなー。
mallocってありましたっけ?
あ、だからやたらとでかい配列とかをスタックにとっちゃダメのはず、なんですが
Freyaってユーザースタック幾つとってるんでしょう?

higuchi




ML Archives