Navigation Log - なびろぐ -
2014/08/07

...X680x0 spirit inside...

この日記はGNSで生成しています。
この日記の画像はOPTPiX webDesigner Ver.4で生成しています。

hauN
Go amazon.co.jp

■ご注文リストから■ [一覧]
■Amazonギフト券■ [購入]
真・女神転生 DEEP STRANGE JOURNEY 真・女神転生 25周年記念スペシャルボックス 【限定版同梱物】 ・レアサントラ& [ゲーム]
真・女神転生 DEE...
Amazonほしい物リスト


2014/08/07 (木)

Z80で1〜100を足すプログラム (プログラム)

_Z80 vs 6502」の「掛け算 - Z80 - HL活用」。「n*(n+1)/2」を求めるという話。

_ まずオリジナル。


        LD DE,0         ; 10(11)
        LD A,100        ; 7(8)
        LD HL,101       ; 10(11)
        OR A            ; 4(5)
        JP NZ,START     ; 10(11)
        EX DE,HL        ; 4(5)
        JR END          ; 12(13)
LOOP1:
        EX DE,HL        ; 4(5)
LOOP2:
        ADD HL,HL       ; 11(12)
START:
        RRA             ; 4(5)
        JR NC,LOOP2     ; 12/7(13/8)
        EX DE,HL        ; 4(5)
        ADD HL,DE       ; 11(12)
        JP NZ,LOOP1     ; 10/10(11/11)
END:
        SRL H           ; 8(10)
        RR L            ; 8(10)


_ この方法、n=100だと343clkだが、n=254だと46+(58*7+30*1)-17+20 = 485clkで、がっくり効率が落ちる。nが小さいととても効率がいいのだけど。

_ 対して、当方のコード。上の手法だと「下の位から足し上げている」のに対して、こちらは「上の位から足し上げている」。桁を送るのに「EX DE,HL」しなくていい分だけ速い。


        LD A,100        ; 7(8)
        LD HL,0         ; 10(11)
        LD DE,101       ; 10(11)
        LD B,7          ; 7(8)
        ; = 38
LOOP:
        ADD A,A         ; 4(5)
        JR NC,P1        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 18/25
P1:
        ADD HL,HL       ; 11(12)
        DJNZ LOOP       ; 13/8(14/9)
        ; = 26/21
        JP P,END        ; 10(11)
        ADD HL,DE       ; 11(12)
        ; = 11/23 = 11
END:
        SRL H           ; 8/10
        RR L            ; 8/10
        ; = 20
        ; TOTAL = 38+(25*3+18*4)+(26*6+21)+11+20 = 393


_ ただし、nが小さくてもループ回数を減らせないため、n=100では393clkで及ばない。n=254だと38+(25*7+18*1)+(26*6+21)+11+20 = 439clkで、やっと上回る。

_ そして、ループ展開版。


        LD A,100        ; 7(8)
        LD HL,0         ; 10(11)
        LD DE,101       ; 10(11)
        ; = 30
P0:
        ADD A,A         ; 4(5)
        JR NC,P1        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 18/25 = 18
P1:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P2        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37 = 37
P2:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P3        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37 = 37
P3:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P4        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37 = 30
P4:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P5        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37 = 30
P5:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P6        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37 = 37
P6:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P7        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37 = 30
P7:
        ADD HL,HL       ; 11(12)
        JP P,P8         ; 10(11)
        ADD HL,DE       ; 11(12)
        ; = 23/35 = 23
P8:
        SRL H           ; 8(10)
        RR L            ; 8(10)
        ; = 20
        ; TOTAL = 30+18+37+37+30+30+37+30+23+20 = 292

_ ループ展開した場合、n=100で292clk、n=254だと30+25+(37*6)+23+20 = 320clk。

_ ただし、この手法だとnが小さい……具体的にはn<16くらい……のときに効率がよくない。頭のほうで「nが十分に小さければ前半を端折る」などの処理を入れることである程度改善できる。


        LD A,100        ; 7(8)
        LD HL,0         ; 10(11)
        LD DE,101       ; 10(11)
        LD B,2          ; 7(8)
        ; = 38
        CP 16           ; 7(8)
        JP NC,P0        ; 10(11)
        ADD A,A         ; 4(5)
        ADD A,A         ; 4(5)
        ADD A,A         ; 4(5)
        ADD A,A         ; 4(5)
        DEC B           ; 4(5)
        ; = 19/44 = 19
LOOP:
        ADD HL,HL       ; 11(12)
        ; = 12
P0:
        ADD A,A         ; 4(5)
        JR NC,P1        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 18/25
P1:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P2        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37
P2:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P3        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37
P3:
        ADD HL,HL       ; 11(12)
        ADD A,A         ; 4(5)
        JR NC,P4        ; 12/7(13/8)
        ADD HL,DE       ; 11(12)
        ; = 30/37
P4:
        DJNZ LOOP       ; 13/8(14/9)
        ; = 13/8
        SRL H           ; 8(10)
        RR L            ; 8(10)
        ; = 20
        ; TOTAL = 38+19+ 12+18+37+37+30+ 13 + 12+18+37+30+30 + 8 + 20 = 359


_ この場合、n=100で359clk、n=254で387clk、n=15のとき263clkでまあまあな結果となる。DJNZをループ展開すればもうちょっとクロックは稼げるが、もはや意味のない領域だろう。

_ ただそもそも、「8bit×8bit=16bit」を速くするためにこのコードを使うのは、コードサイズから考えるとあんまり効率よくないと思うんだ……(苦笑)。


[URL] [View Log()] [Trackback]
Name: Comment:



メールはこちらへ...[後藤浩昭 / Hiroaki GOTO / GORRY / gorry@hauN.org]

「表紙へ戻る」
「会議室」 「最新版」 「なびろぐindex」 「GNSソースを読む」