リンクしているウィキペディアの記事から実装を取得する場合...
send(to, from, count)
register short *to, *from;
register count;
{
register n=(count+7)/8;
switch(count%8){
case 0: do{ *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
}while(--n>0);
}
}
...そして「高レベル」do
/while
ループをアセンブリレベルif
/に置き換えます。goto
これはコンパイラが実際にそれを...に減らします。
send(to, from, count)
register short *to, *from;
register count;
{
register n=(count+7)/8;
switch(count%8){
case 0: do_label: *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
if (--n>0) goto do_label;
}
}
... do / whileスコープがローカル変数を導入しなかったこの使用法では、スイッチをバイパスするケース0に戻って、 count%8を評価する必要があります(%は物事のスキームではかなり高価な操作です)。
それがクリックするのに役立つことを願っていますが、そうではないかもしれません...?:-)
なぜダフは8を使用したのですか?16、65536などになります。コードサイズのため?別の理由はありますか?たとえば、キャッシュやパイプラインのメリット。
収穫逓減の場合。8つのデータコピーごとにチェックとジャンプを実行する--n > 0
必要があることは、大きな割合のオーバーヘッドではありませんが、コードのサイズ(ソースとキャッシュ内のコンパイル済みコードの両方)は依然としてかなりタイトです。多分それはオーバーヘッドに対して90または95%の作業になるでしょう、それは明らかに十分に良かったです。さらに、概念を説明して他の人と共有するために、トム・ダフは、1ページまたは10ページではなく、典型的な80x25端末のコードに相当するものにすることを好んだかもしれません。