MC6800のプログラミングテクニック(28) ループ処理(2)

BASICMASTER

前回はstrcmpの例を見てきた。今回はstrchrの話。

strchrは検索文字として ‘\0′ が渡される場合があるので、注意。

通常は 文字が見つからずに末端の0に至った場合は NULLを返すが、’\0’ を検索していたときはそのアドレスを返す必要がある。


char *strchr(const char *s,int c)
{
  while (*s && (*s!=c)) {
    s++;
  }
  return (*s==c)? s: NULL;
}

アセンブラで素直に書いてみる

探したい文字はAccBに入っているものとする。前回同様に ループ末で分岐、tstは使わない形で書いてある。


  dex
loop:
  inx
  cmpb 0,x
  beq found
  ldaa 0,x
  bne loop
  :
found:


インデックスアドレッシングは遅い

MC6800のインデックスアドレッシングは遅いのである(5〜7 cyc)。上記コードでは2回使われていて、ループ内部は 4+5+4+5+4 = 22cyc かかる。

比較と0テストで2回インデックスアドレッシングを使っているのを 1回に減らしてみよう。ロードは減らせないので比較を変更する。

4+5+2+4+2+4 = 21cyc である。ldaaで0かどうかはわかるのに、tstを実行しているのが いかにも無駄である。


  dex
loop:
  inx
  ldaa 0,x
  cba
  beq found
  tsta
  bne loop
  :
found:


終了時に判別する

順序を入れ替えて、先に文字列末かどうかを判定する。
0を見つけたときに、見つけたい文字が0だったかを再確認するように変更。

4+5+4+2+4 = 19cyc になった。

(文字が見つかっても見つからなくても)6cyc余計に必要だが、ループあたり3cyc減っているので、2文字以上あれば元は取れる。


  dex
loop:
  inx
  ldaa 0,x
  beq break
  cba
  bne loop
found:
  :
break:
  cba
  beq found
  :


コメント

タイトルとURLをコピーしました