訂正 LSI-C80 → LSI C-80 LSI-C86 → LSI C-86
先ず第一に、80と86ではコードジェネレータが違うこと。 →80版は86版ほどタイトなコードは生成しない。 第二に、初回のジャンプを省略しようかと言うレベルの話をしていること。 →8086のコードは参考にしかならない。 全く的外れと言わざるをえない。
>>953 >先ず第一に、80と86ではコードジェネレータが違うこと。
>→80版は86版ほどタイトなコードは生成しない。
じゃあどんなコード吐くの? 参考に晒してくれたっていい罠。
>第二に、初回のジャンプを省略しようかと言うレベルの話をしていること。
少なくとも
>>930-931 はそんな話してない訳だが。
>→8086のコードは参考にしかならない。
参考になるならいいじゃん。アホか?
>>953 >第二に、初回のジャンプを省略しようかと言うレベルの話をしていること。
そこまで気にすんなら関数呼び出しのコストも削れよw
>>954 名前:デフォルトの名無しさん[sage] 投稿日:2012/12/19(水) 12:27:27.27
そう真っ赤になるなって。自分の投稿時間でも眺めて和めよ。
和んだ
>>930 >8085用のLSIC-80で、3行分溜めてからまとめるコードを以下のように書いていた。
> strcpy(dst,1行目);
> strcat(dst,2行目);
> strcat(dst,3行目);
>strcpyした末尾アドレスをそのまま返せばstrcpyと同程度の性能になるのに許せん!
実際その部分が全体のパフォーマンスにどの程度影響及ぼしてるわけ?
多少効率が悪かろうとも、間に合ってるなら以降の作業は徒労ということになるが。
959 :
931 :2012/12/19(水) 16:54:57.38
sprintfで実数変換使うと間に合わない、整数変換でも幾つもやると同様、ぐらい。 4800BPSを4CH同時に入出力してて、あるCHがこの例です。1CHだけならイイが、 4CHみんな整数変換とかstrcatを使うと危ないので軽くできればしておきたいです。 間に合わない=受信ringで周回遅れが発生して行の再構成が失敗します。 clockは3.072MHzで、これを8253で分周して8251用と10mS割込用のclock作ってます。 まあ、暇だから最適化で遊んでるってのもありますけど。
sprintf() 既に使ってるなら、 sprintf(dst, "%s%s%s", 1行目, 2行目, 3行目); とか書けば保守性は向上するな。 sprintf()の実装や連結する文字列のバイト数によっては負荷ともなりうるが。
>>959 >sprintfで実数変換使うと間に合わない、整数変換でも幾つもやると同様、ぐらい。
重い箇所分かってんなら最適化で一番効果が期待できるのはそこだが?
>>930 >8085用のLSIC-80で、3行分溜めてからまとめるコードを以下のように書いていた。
> strcpy(dst,1行目);
> strcat(dst,2行目);
> strcat(dst,3行目);
最初からひとつのバッファに3行分溜めればまとめる必要もねんじゃね?
Cで速度最優先なら、str系ではなく、自分で長さを保持して全てmemcpy。 それでもダメってところで、ようやくアセンブラ。
>sprintfで実数変換使うと間に合わない、 LSI C-80って基本的な仕様が古いみたいだし、実数はfloatでも一旦doubleに昇格してから 演算するとかですげえ遅いんじゃないの?C89以前では普通だったけど。 実数が本当に必要かも検討するべき。
LSI Cは実数遅いよ。余りチューンしてないってpnoriさんが言ってた。 まして80じゃぁしょうがない。多分自力で固定小数点数ライブラリを作るのが一番。
>>963 >Cで速度最優先なら、str系ではなく、自分で長さを保持して全てmemcpy。
8085での実装なら、memcpy()よりstrcpy()の方が速い。
967 :
966 :2012/12/19(水) 19:45:54.67
訂正 8085での実装なら、memcpy()よりstrcpy()の方が速い。 ↓ 8085での実装で、場合分けによる処理の最適化をしない前提なら、memcpy()よりstrcpy()の方が速い。 LSI C-80での実装がどうなってるかは知らん。
969 :
931 :2012/12/20(木) 06:43:03.90
%16 ; ここがwhile の行。 __2: LDAX D MOV M,A ORA A JZ __3 %17 INX H %18 INX D %19 JMP __2 __3: %20 RET JMPが2つあるのでサイズ最小ではないけど、素直なコードですね。 _asm_が混じるcコードより可読性はグー! memcpyよりstrcpyのほうが速いのは知って使ってます。
>>969 成る程、86版とは違うコードになるんだなあ。
1ループ中にジャンプ命令が2回あるからコピーする文字列が長いと86版に比べて効率は悪いが、
逆に、コピーする文字列が""で、結果1バイトしかコピーしない場合には効率は良いとも言えるな。
JZ __3
(略)
__3:
RET
のところは
RZ
になってればループを抜けなかった際のサイクル数が少なかったのに惜しい。
971 :
931 :2012/12/20(木) 13:55:00.11
R<条件> と、C<条件> はLSIC-80に実装されてないんですよね。なので、 if( r_ptr ^ w_ptr ) func( ); は、lda r_ptr、lxi H,w_ptr、xra M、JZ 飛び越し、call func が出ます。 これを lhld r_ptr、mov A,H、xra L、cnz func と、最適化しました。 (r_ptrとw_ptrは並んでいるので) メインループ中にこれが4種類あるので、 メモリアクセス削減になってます。
2ちゃんもひと少なくなったな
973 :
931 :2012/12/20(木) 17:14:18.48
8085用 romlibのcコード読んでたら、strncat( ) は目的stringの末尾にnullをsetする だけなのに、strncpy( ) は、目的stringがソースより長いとき 「残りを全て0で埋める」 ように書かれていました。 これは実害は無いにしろ、「余計なこと」 ですね。
974 :
931 :2012/12/22(土) 05:50:34.74
>>970 ループ中に毎回NOPのジャンプが実行されるのが、素直なコードの悔しい所ですね
char*stpcpy2(char *s, const char *t) {
goto do2;
do1: s++; t++;
do2: if (*s = *t) goto do1;
return(s);
} これだと頭のジャンプ1回が静的動的に無駄なだけで、あとはASMのコードと同性能
_asm_で書くより可読性は良いから、cでの実装にはこれがベストかと。
>>973 それがstrncpy()の奇妙な仕様。なので、余計ではない。
976 :
931 :2012/12/22(土) 12:37:11.14
え〜?? ほんとだ。わざわざそのように断ってある。なんでこんなことに なってるんだろう? 末尾nullだけでは困る事情がかつてあったのだろうか。
977 :
931 :2012/12/22(土) 13:08:23.06
>>974 をfor( ; (*s=*t); s++,t++ ) ; と書くと、素直版と同じコードになっちゃうんですね。
forで、頭JMPで実行条件判定に飛び込むパターンも見たことあるのですが、何が
決め手になるのかよく判らないなあ。
978 :
931 :2012/12/28(金) 04:30:02.13
strcat( d, s ) の中身:strcpy(d+strlen(d),s); return( d ); の展開が↓ push H push D pop H push H push H call LAUTO4 call strlen mov C,L mov B,H call LAUTO4 DAD B POP D call strcpy call LAUTO2 pop B pop B ret コールが5回もあるの(*o*) あんまりだ!
979 :
931 :2012/12/28(金) 04:36:00.53
ASMにしてみたのがこれ: 合ってるよね? strcat_: ; char *strcat(char *s, const char *t) { push H ; 第1引数を保存 mov A,M inx H ora A jnz $-3 ; 末尾を探す dcx H ; 末尾アドレスに戻す call strcpy_ ; その位置にcopy pop H ; 第1引数を復元(HL=返却値) ret
>>979 call して pop hl する代わりに、pop af して jmp してはどうだろう。
あ、なんだ、保存する必要さえなかったか。
>>979 速度優先なら、PUSH H〜POP HはBC に退避〜復帰させた方が早い。
但しstrcpy()の中で破壊されないこと前提になるから保守性は低下する。
strcpy()も展開した方がいいな、速度優先なら。
失業したおっさんらに質問です OS創りたいのですが 何から始めれば良いでしょう
マジレスするが、まずは失業しておかないと、創る時間とれないよ
失業せずにOSを作れないようなら、シングルタスクのOSを作る頭脳しかない。
989 :
デフォルトの名無しさん :2012/12/28(金) 13:27:11.77
今日の大喜利会場はここですか?
990 :
979 :2012/12/29(土) 04:06:22.83
>>980 動作変わっちゃいませんか?返却値は目的stringの頭ですけど、
strcpyする時は目的stringの末尾ですよね。
>>982 速度だけ優先ならそうですね。libであることを考慮すると速度・サイズ両面で
納得のゆく落とし所、ということで979にしました。 同サイズで速度ちょっと改善版:
strcat_: ; char *strcat(char *s, const char *t) {
push H ; 第1引数を保存
xra A
cmp M
inx H
jnz $-2 ; 末尾を探す
dcx H ; 末尾アドレスに戻す
call strcpy_ ; その位置にcopy
pop H ; 第1引数を復元(HL=返却値)
ret
徹底するなら速度版とサイズ版2種のlibを用意するのがイイですね。
991 :
979 :2012/12/29(土) 04:13:24.07
発端は、「libは、コンパイラ開発メーカーの(自分より頭のイイ)人が書くのだから、 速度・サイズ両面で充分練られた物だろう」 と思いこんでいたのが違った、という話。 乗除算のルーチンなんかはきっちりコンパクトでしたけどね。 stringがこんだけルーズだと、printf系なんか読んだら憤死するかも(^o^)
992 :
デフォルトの名無しさん :2012/12/29(土) 05:53:01.81
うめますね(^o^)
993 :
デフォルトの名無しさん :2012/12/29(土) 05:53:36.75
うめ
994 :
デフォルトの名無しさん :2012/12/29(土) 08:01:12.51
うめ
996 :
デフォルトの名無しさん :2012/12/29(土) 08:38:16.29
うめ
JR $-2
うめ
うめ
76
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。