どのように正確に一つは、最初にロードされた値を計算していますか?
* 16000000 = 8000000 0.5秒
そう完全ループは、AVRレジスタは8ビットであり、(ゼロからゼロへ)R20およびR19ループの合計サイクルを知って> =サイクルの総量を計算256回(dec 0 = 255
)。 dec
は1サイクルです。 brne
は、条件(分岐)が発生した場合は2サイクル、発生しない場合は1サイクルです。
だから、最も内側のループ:255 *(1 + 2)+ 1 *(1 + 1)= 767サイクル(255倍分岐がある:
L1: dec r20
brne L1
は、ゼロからゼロ(r20=0
)することです1回は通過する)。
r19
を扱う第二包装ループはである:255×(767 + 1 + 2)+ 1×(767 + 1 + 1)= 197119サイクル
単一r18
ループ分岐がある場合197119 + 1 + 2 = 197122サイクルとなる。 (分岐が取られていない197121 =遅延ループの最後の終了、私は次のステップでこれを-1とします)。
ここでは、最初にr18
を計算するのに十分ですが、最初にO(1)コードで合計サイクルを調整してみましょう。これは、1サイクルを要するldi
命令の3倍です:total2 = 8000000 - (1 + 1 + 1) + 1 = 7999998 ...待って、そこに最後の+1は何ですか?それは、最後のr18
ループが最終的でない、すなわち197122サイクルと同じ費用を負うようにするために、遅延するための偽の追加サイクルです。 r18 = (7999998 + 197122 - 1) div 197122 = 41
:
そして、それはこれだけです、初期r18
は少なくとも 7999998サイクルを待つために十分でなければなりません。 "+ 197122 - 1"の部分は、豊富なサイクルが拘束条件を満たすことを確認します:0 <= abundant_cycles < 197122
(197122の剰余によって剰余)。
41 * 197122 = 8082002
...これはあまりにも多くのですが、今は遅延微調整するために、特定の値にもr19
とr20
を設定することで、余分なサイクルをダウン剃ることができます。それで、どれくらい削られるのですか? 8082002 - 7999998 = 82004
サイクル。
単一のr19
ループは、分岐時に770サイクル、終了時に769サイクルを要するので、再び82004を82003に調整することによって769を避けるようにしましょう。 82003 div 770 = 106
:106 r19
ループはスキップできます。r19 = 256 - 106 = 150
。これで81620サイクルが削られますので、82003 - 81620 = 383サイクル以上削ってください。
単一のr20
ループは分岐時に3サイクル、終了時に2サイクルかかる。再び、私は、ループを2回だけ退出することを考慮に入れます - > 383 => 382を剃ること。 382 div 3 = 127
、残りは1。r20 = 256 - 127 = 129
であり、残りの3つのサイクルを削るために1つ少ない(残りの部分をカバーする)= 128です。それから、2サイクル(3-1)の待ち時間がなくなり、完全な8ミルになります。
ので(他の何かによって中断されていない場合)私の計算によると
ldi r18, 41
ldi r19, 150
ldi r20, 128
L1: dec r20
brne L1
dec r19
brne L1
dec r18
brne L1
はまさに8000000から2サイクルを待つ必要があります。
のは、検証してみましょう:
初期r20
:127 * 3 + 1 * 2 = 383サイクル
を 初期r19
:1 *(383 + 1 + 2)+ 148 *(767 + 1 + 2) + 1×(767 + 1 + 1)= 115115サイクル (すなわち、最終的な一つである149回のフルタイムr20
サイクル-1によるbrne
を出ると、次いで、r20
不完全サイクル一度初期'S)
r18
合計:1 * (115115 + 1 + 2)+39 *(197119 + 1 + 2)+ 1 *(197119 + 1 + 1)= 7999997サイクルである。
そして3 ldi
は3サイクル= 7999997 + 3 = 80000000.
され、不足している2サイクルが見られることをどこにもありませんので、私はどこかでミスを犯しました。
あなたが見ることができるように、背後にある数学が合理的にシンプルですが、手で行うことは非常に世俗的な、そしてミスを起こしやすい...
ああ、私は間違いをしたところ、私が知っていると思います。私が豊富なサイクルを削り取っているとき、終了ループは関与していません(それは実際の遅延プロセスの一部です)。したがって、to_shave_offサイクルを-1で調整すべきではありません。その後、r19 = 106
の後、私はまだ384サイクルを削り取る必要があり、それはちょうどr20 = 256-128 = 128
から削り取るために、正確に384/3 = 128ループです。余り、欠けていないサイクル、完璧な8ミル。
この逆の計算に従うのが難しい場合は、2ビットレジスタ(0..3値のみ)を想像し、r18 = r19 = r20 = 2の紙の同様のループで行い、それがどのように進化しているかを見るために手動で循環させる。つまり、3xldi = +3、dec r20、brne、dec r20、brne(スキップ)= +5サイクル、dec r19、brne = +3、...など。
編集:彼のリンクでJesterによって。そして、私はあなた自身のオンライン電卓を作成する簡単な数式にこれをクリーンアップするにはあまりにも怠惰です。
1.命令セットリファレンスで 'brne'が何を行うかを調べます。結果が正か負かにかかわらず、ゼロでない場合はそれがとられていると仮定します。だから、ループを符号なしカウンターを使用するものと考えてください。 –
参照[this](https://stackoverflow.com/a/23478769/547981)と[this](https://stackoverflow.com/q/35750663/547981) – Jester
計算するために命令サイクルを計算する必要がありますこのループが消費する時間。このループはラベル「L1: '0x00299680(2,725,504)回」を繰り返します。 (0x29 = 41d、0x96 = 150d、0x80 = 128d)。ループ中にISR(割り込みサブルーチン)が実行された場合、サイクルを使用して計算する時間は無効です。遅延ループ中にISRをディセーブルするには、opportune命令を使用します。 –