Vlákno názorů k článku Vývoj pro ZX Spectrum: mikroprocesor Zilog Z80 a smyčky v assembleru od _dw - Tak jeste optimalizace pro posledni 16 bitovou smycku. ...

  • Článek je starý, nové názory již nelze přidávat.
  • 14. 2. 2023 6:25

    _dw

    Tak jeste optimalizace pro posledni 16 bitovou smycku.

    org 0x8000

    start:
    ld hl, 0x59FF ; adresa pro zápis
    ld a, 0x57 ; stop pro horni bajt adresy

    loop:
    ld (HL),L ; zápis hodnoty na adresu (HL)
    dec HL ; snížní adresy i zapisované hodnoty
    cp H ; počitadlo vnější smyčky
    jp nz, $-3 ; skok pokud nejsme pod atributovou pamětí
    ret

    ORG 8000
    8000: label start
    8000:21FF59 LD HL, 59FF
    8003:3E57 LD A, 57
    8005: label loop
    8005:75 LD (HL), L
    8006:2B DEC HL
    8007:BC CP H
    8008:C20580 JP NZ, 8005
    800B:C9 RET

    To by melo byt o 4 bajty kratsi, ale skoro o 512 taktu pomalejsi (jsem linej to pocitat). Dalo by se to zkratit o další bajt a zpomalit o dalsich 1024 taktu prostym nahrazenim instrukce skoku za relativni skok.

    Djnz je sice efektivni, ale ne vzdy.

  • 17. 2. 2023 5:18

    _dw

    Nasel jsem o bajt kratsi reseni a jeste k tomu rychlejsi.
    Neni to ale 16 bitova smycka, ale 8 bitova, jen staci zvednou a snizit H.

    Puvodni (12 bajtu a cca 27 taktu na bajt, oproti 16 bajtu a cca 26 taktu na bajt z clanku):

        org 0x8000
    
        ; t= 10+7+10+512*(7+6+4+10)=27+512*27=13851
    start:
        ld   HL, 0x59FF         ; 3:10  adresa pro zápis
        ld    A, 0x57           ; 2:7   stop pro horni bajt adresy
    
    loop:
        ld  (HL),L              ; 1:7   zápis hodnoty na adresu (HL)
        dec  HL                 ; 1:6   snížní adresy i zapisované hodnoty
        cp    H                 ; 1:4   počitadlo vnější smyčky
        jp   nz, loop           ; 3:10  skok pokud nejsme pod atributovou pamětí
        ret                     ; 1:10

    Nove (11 bajtu a cca 38/2=19 taktu na bajt):

        org 0x8000
    
        ; t= 10+256*(4+7+4+7+4+12)-5+10=15+256*38=9743
    start:
        ld   HL, 0x5800         ; 3:10  adresa pro zápis
    
    loop:
        inc   H                 ; 1:4
        ld  (HL),L              ; 1:7   zápis hodnoty na adresu (HL)
        dec   H                 ; 1:4
        ld  (HL),L              ; 1:7   zápis hodnoty na adresu (HL)
        inc   L                 ; 1:4   zvýšení adresy i zapisované hodnoty
        jr   nz, loop           ; 2:7/12
        ret                     ; 1:10

    Tohle reseni by slo prepsat na o neco pomalejsi variantu, ale ktera je schopna zvladnout vice 256 bajtovych bloku.
    Univerzalnejsi (11 taktu a cca 41/2=20.5 taktu na bajt):

        org 0x8000
    
        ; t= 7+256*(7+7+4+7+4+12)-5+10=12+256*41=10508
    start:
        ld    L, 0x00           ; 2:7   lo(adresa) pro zápis
    loop:
        ld    H, 0x58           ; 2:7   hi(adresa) pro zápis
        ld  (HL),L              ; 1:7   zápis hodnoty na adresu (HL)
        inc   H                 ; 1:4
        ld  (HL),L              ; 1:7   zápis hodnoty na adresu (HL)
        inc   L                 ; 1:4   zvýšení adresy i zapisované hodnoty
        jr   nz, loop           ; 2:7/12
        ret                     ; 1:10

    PS: Jeste by slo pouzit smycku kde counter by byl carry!
    Protoze se ma zopakovat jen jednou (kod probehne 2x) a nikde carry nemenime.
    Ale u takhle kratkeho kodu se to vyplati spis zduplikovat.

    or A
    loop:
    ...
    ccf
    jr c,loop