Vlákno názorů k článku Kopie datových bloků na ZX Spectru: přenášení bajt po bajtu od _dw - Diky za clanek. Pouzit u skoku PE je svatecni...

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

    _dw

    Diky za clanek.
    Pouzit u skoku PE je svatecni pocit. .)

    V kapitole 3. mas napsano:

            ld   bc, SCREEN_ADR
            ld   de, SECOND_SCREEN_BLOCK
            ld   hl, SCREEN_BLOCK_SIZE
            call mem_copy
    Poznámka: volba registrových párů není náhodná, jak uvidíme v navazujících kapitolách.

    To muze nekoho zmast, protoze uz v kapitole 6 je:

    ld   hl, SCREEN_ADR           ; adresa zdrojového bloku
    ld   de, SECOND_SCREEN_BLOCK  ; adresa cílového bloku
    ld   bc, SCREEN_BLOCK_SIZE    ; velikost přenášených dat
    ldir

    Te mem_copy rutine z kapitoly 16 se neda vubec nic vytknout, imho je i lepsi nez hrani se zasobnikem. Tam je spousta problemu. Vypinat interupty. Pokud uz si hrajeme o nejvyssi rychlost, tak se tam jeste pridavaji IX a IY registrove pary. Takze pocet prenaseneho bloku neni nasobek 2. Pak se jeste musi resit, jestli to chces fakt rozbalit pres celou kopirovanou oblast a mit kod tim padem o podobne velikosti, nebo nad tim udelat nejakou smycku a pak resit, ze jednou jde ukazatel zasobniku nahoru a podruhe dolu. Takze muzes mit i zdroj prevraceny v bufferu. Same komplikace.

    U toho elegantniho rozbaleneho LDI bych jen podotknul, ze nemusis mit

            ld   a, b                ; kontrola BC na nulu
            or   c
            ret  z                   ; při prázdném bloku podprogram ukončíme
    
            ld   a, 16               ; na základě hodnoty v C vypočteme, kolik
            sub  c                   ; insturkcí LDI se má na začátku přenosu přeskočit
            and  15                  ; maximálně se přeskočí 15 instrukcí ze 16
    
            add  a, a                ; vynásobit dvěma protože LDI je dvoubajtová instrukce
            ld   (jump_address), a   ; uložíme offset do tohoto paměťového místa
            jr   $                   ; relativní skok přečte offset z ^
    jump_address equ $-1             ; trik jak zasáhnout do operandu instrukce JR

    dokud je ta velikost prenasenych dat konstanta.
    Pak to jen volas misto:
    call mem_copy
    napriklad takto:
    call repeat+2*((16-SCREEN_BLOCK_SIZE)& 15)
    a nechas si spocitat ten skok prekladacem.

  • 2. 5. 2023 12:08

    Pavel Tišnovský
    Zlatý podporovatel

    dik za doplneni.

    jinak na okraj: zrovna ted v sobotu jsem zpovidal dva sinclairisty (jeden dela pekna dema) a ti rikali, ze kdyz jde fakt o kopie cele VRAM, tak si nechaji ty rozbalene smycky s push/pull vygenerovat za behu. Chce to ale zhruba 2x tolik pameti, nez kopirovana data :) Ale ze vetsinou to neni tak kriticke a staci rozbaleni LDI.

  • 2. 5. 2023 17:55

    _dw

    Jo pro demo je to pouzitelne, ale kdyz si predstavim ze mam 48kb volne ram. Z toho si odectu nejake misto na zasobnik a buffer obrazovky tak jsem nekde kolem 40kb. Pak misto na tu rutinu a kdyby to bylo ldi tak jsem na 26.5 kb a to je sakra malo, pokud delam hru a spoustu mista mi zabira grafika. To fakt neni 64kb.

    Schvalne jsem se snazil prepsat tu samomodifikujici rutinu na variantu, kterou muze pouzit i ROM rutina a vzhledem k tomu, ze pri volani je obsazene i HL a nejde to diky LDI zmenit tak je to zajimavy problem, protoze "jp HL" (oficialne to je "jp (HL)") nejde pouzit. Ale pomohl jsem si pres RET.

    Prepsal jsem i co se kopiruje na atributy, protoze u textu, ktery ani nedosahuje do konce tretiny obrazovky to neni prukazne. A aby to bylo citelnejsi tak je lepsi si pomoct i v basicu tiskem na obrazovku predtim.

    10 FOR a=0 TO 16
    20 PRINT AT a,0;a
    30 NEXT a
    40 RANDOMIZE USR 32768
    50 PAUSE 0
    ; Example #88x:
    ;    Print color on screen + copy it to second part of screen using unrolled loop.
    
    ATTR_ADR            equ $5800
    SCREEN_BLOCK_SIZE   equ 130
    SECOND_SCREEN_BLOCK equ $5901
    
    ENTRY_POINT         equ $8000
    
            org ENTRY_POINT
    
            ; Vstupní bod celého programu
    start:
            call draw_attr                ; vyplnění prvni tretiny barvou
            ld   hl, ATTR_ADR             ; adresa zdrojového bloku
            ld   de, SECOND_SCREEN_BLOCK  ; adresa cílového bloku
            ld   bc, SCREEN_BLOCK_SIZE    ; velikost přenášených dat
            call mem_copy
            ret
    
    repeat:
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            ldi                      ; provést přenos jednoho bajtu
            jp   pe, repeat          ; ukončit blokový přenos při BC==0
            ret                      ; návrat z podprogramu
    mem_copy:
            ld   a, b                ; kontrola BC na nulu
            or   c
            ret  z                   ; při prázdném bloku podprogram ukončíme
    
            ld   a, 16               ; na základě hodnoty v C vypočteme, kolik
            sub  c                   ; insturkcí LDI se má na začátku přenosu přeskočit
            and  15                  ; maximálně se přeskočí 15 instrukcí ze 16
            add  a, a                ; vynásobit dvěma protože LDI je dvoubajtová instrukce
            exx
            add  a, low repeat
            ld   c, a
      if ((0xFF & repeat) >= (256-2*16))
            adc  a, high repeat
            sub  c
            ld   b, a
      else
            ld   b, high repeat
      endif
            push bc                  ; menit stinove BC je bezpecne pro navrat do basicu
            exx
            ret
    
    
    draw_attr:
            ld   a,1*8+2
            ld  de,ATTR_ADR
            ld   b,0
    draw_loop:
            ld   (de),a              ; zápis hodnoty na adresu (DE)
            inc  de
            djnz draw_loop           ;
            ret                      ; návrat z podprogramu
    
    
    end ENTRY_POINT
  • 3. 5. 2023 2:38

    _dw

    Podporuje to pasmo, kterym se prekladaji ty priklady zrovna. Ale umi to i sjasmplus.

    pasmo ma vse 16 bitove a unsigned
    sjasmplus je myslim 32 bit signed a umi vic operatoru, ale na rozdil od pasma neumi ?

    pasmo ma chybu, a nebo featuru v tom ze uvodni - vyhodnocuje skoro nakonec takze:

    -5+3 =-8

    https://pasmo.speccy.org/pasmodoc.html

    ## (see note)
    $, NUL, DEFINED
    *, /, MOD, %, SHL, SHR, <<, >>
    +, - (binary)
    EQ, NE, LT, LE, GT, GE, =, !=, <, >, <=, >=
    NOT, ~, !, +, - (unary)
    AND, &
    OR, |, XOR
    &&
    ||
    HIGH, LOW
    ?

    Pokud chces v pasmu nasobit ve vyrazu nejake dve 16 bitova cisla, ale signed a vysledek ma byt 32 bitovy signed, tak je to docela orisek jak to udelat... :) kdyz pasmo umi jen 16 bit unsigned.

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'PUSH(abc,def) MMUL'
                            ;[8:42]     abc def m*   ( -- +((abc)>>8)*((def)>>8)+(low(abc))*((def)>>8)>>8+((abc)>>8)*(low(def))>>8+((low((low(abc))*((def)>>8)))+(low(((abc)>>8)*(low(def))))+(low(abc))*(low(def))>>8)>>8-((abc)>>15)*(def)-((def)>>15)*(abc) +(abc)*(def) )
        push DE             ; 1:11      abc def m*
        push HL             ; 1:11      abc def m*
        ld   DE, +((abc)>>8)*((def)>>8)+(low(abc))*((def)>>8)>>8+((abc)>>8)*(low(def))>>8+((low((low(abc))*((def)>>8)))+(low(((abc)>>8)*(low(def))))+(low(abc))*(low(def))>>8)>>8-((abc)>>15)*(def)-((def)>>15)*(abc); 3:10      abc def m*
        ld   HL, +(abc)*(def); 3:10      abc def m*
    ; seconds: 0           ;[ 8:42]

    O neco kratsi by to bylo kdyby jsi chtel u16*u16=u32

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'PUSH(abc,def) UMMUL'
                            ;[8:42]     abc def um*   ( -- +((abc)>>8)*((def)>>8)+(low(abc))*((def)>>8)>>8+((abc)>>8)*(low(def))>>8+((low((low(abc))*((def)>>8)))+(low(((abc)>>8)*(low(def))))+(low(abc))*(low(def))>>8)>>8 +(abc)*(def) )
        push DE             ; 1:11      abc def um*
        push HL             ; 1:11      abc def um*
        ld   DE, +((abc)>>8)*((def)>>8)+(low(abc))*((def)>>8)>>8+((abc)>>8)*(low(def))>>8+((low((low(abc))*((def)>>8)))+(low(((abc)>>8)*(low(def))))+(low(abc))*(low(def))>>8)>>8; 3:10      abc def um*
        ld   HL, +(abc)*(def); 3:10      abc def um*
    ; seconds: 0           ;[ 8:42]

    Pro signed deleni 16 bitove konstanty 16 bitovou konstantou a jeste ziskanim zbytku by vypadalo takto:

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'PUSH(abc,def) DIVMOD'
                            ;[8:42]     abc def /mod   ( -- +((((abc)|(def))>>15) xor 1)*(abc)mod(def)+(((~(abc))&(def))>>15)*(abc)mod(-(def))-(((abc)&(~(def)))>>15)*(-(abc))mod(def)-(((abc)&(def))>>15)*(-(abc))mod(-(def)) +((((abc)|(def))>>15) xor 1)*(abc)/(def)-(((~(abc))&(def))>>15)*(abc)/(-(def))-(((abc)&(~(def)))>>15)*(-(abc))/(def)+(((abc)&(def))>>15)*(-(abc))/(-(def)) )
        push DE             ; 1:11      abc def /mod
        push HL             ; 1:11      abc def /mod
        ld   DE, +((((abc)|(def))>>15) xor 1)*(abc)mod(def)+(((~(abc))&(def))>>15)*(abc)mod(-(def))-(((abc)&(~(def)))>>15)*(-(abc))mod(def)-(((abc)&(def))>>15)*(-(abc))mod(-(def)); 3:10      abc def /mod
        ld   HL, +((((abc)|(def))>>15) xor 1)*(abc)/(def)-(((~(abc))&(def))>>15)*(abc)/(-(def))-(((abc)&(~(def)))>>15)*(-(abc))/(def)+(((abc)&(def))>>15)*(-(abc))/(-(def)); 3:10      abc def /mod
    ; seconds: 0           ;[ 8:42]

    No a pak jsou jeste vetsi hruzy :D
    Nekdy to 32 bitove cislo musi mit nejaky pocet nejvyssich bitu nulovy a je potreba prave ten ? operator

    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'PUSH(hi,lo,abc) UMDIVMOD'
    
      .warning Pasmo does not support 32 bit numbers and M4 does not know all values(They can only emulate 28-bit/12-bit or 16-bit/16-bit without checking the range): "hi<<16+lo abc um/mod"
                            ;[8:42]     hi lo abc um/mod   ( -- +((((((hi) mod (abc)<<4)mod (abc)<<4)mod (abc)<<4)mod (abc)<<4)mod (abc)+(lo) mod (abc))mod (abc) +((hi) mod (abc)<<4+(lo)>>12)/(abc)<<12+(((hi) mod (abc)<<4+(lo)>>12)mod (abc)<<4+(lo)<<4>>12)/(abc)<<8+((((hi) mod (abc)<<4+(lo)>>12)mod (abc)<<4+(lo)<<4>>12)mod (abc)<<4+(lo)<<8>>12)/(abc)<<4+(((((hi) mod (abc)<<4+(lo)>>12)mod (abc)<<4+(lo)<<4>>12)mod (abc)<<4+(lo)<<8>>12)mod (abc)<<4+(15& (lo)))/(abc) )
        push DE             ; 1:11      hi lo abc um/mod
        push HL             ; 1:11      hi lo abc um/mod
        ld   DE, +((((((hi) mod (abc)<<4)mod (abc)<<4)mod (abc)<<4)mod (abc)<<4)mod (abc)+(lo) mod (abc))mod (abc); 3:10      hi lo abc um/mod
        ld   HL, +((hi) mod (abc)<<4+(lo)>>12)/(abc)<<12+(((hi) mod (abc)<<4+(lo)>>12)mod (abc)<<4+(lo)<<4>>12)/(abc)<<8+((((hi) mod (abc)<<4+(lo)>>12)mod (abc)<<4+(lo)<<4>>12)mod (abc)<<4+(lo)<<8>>12)/(abc)<<4+(((((hi) mod (abc)<<4+(lo)>>12)mod (abc)<<4+(lo)<<4>>12)mod (abc)<<4+(lo)<<8>>12)mod (abc)<<4+(15& (lo)))/(abc); 3:10      hi lo abc um/mod
    ; seconds: 0           ;[ 8:42]
    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'PUSH(hi,lo,abc) FMDIVMOD'
    
      .warning Pasmo does not support 32 bit numbers and M4 does not know all values(They can only emulate 16-bit/16-bit without checking the range): "hi<<16+lo abc fm/mod"
                            ;[8:42]     hi lo abc fm/mod   ( -- +((((hi)|(abc))>>15) xor 1)*(lo)mod(abc)+(((~(hi))&(abc))>>15)*(((lo)mod(-(abc))!=0)&((abc)+(lo)mod(-(abc))))+(((hi)&(~(abc)))>>15)*((((-(lo))mod(abc))!=0)&((abc)-(-(lo))mod(abc)))-(((hi)&(abc))>>15)*(-(lo))mod(-(abc)) +((((hi)|(abc))>>15) xor 1)*(lo)/(abc)-(((~(hi))&(abc))>>15)*((lo)/(-(abc))-(((lo)mod(abc))!=0))-(((hi)&(~(abc)))>>15)*((-(lo))/(abc)-(((lo)mod(abc))!=0))+(((hi)&(abc))>>15)*(-(lo))/(-(abc)) )
        push DE             ; 1:11      hi lo abc fm/mod
        push HL             ; 1:11      hi lo abc fm/mod
        ld   DE, +((((hi)|(abc))>>15) xor 1)*(lo)mod(abc)+(((~(hi))&(abc))>>15)*(((lo)mod(-(abc))!=0)&((abc)+(lo)mod(-(abc))))+(((hi)&(~(abc)))>>15)*((((-(lo))mod(abc))!=0)&((abc)-(-(lo))mod(abc)))-(((hi)&(abc))>>15)*(-(lo))mod(-(abc)); 3:10      hi lo abc fm/mod
        ld   HL, +((((hi)|(abc))>>15) xor 1)*(lo)/(abc)-(((~(hi))&(abc))>>15)*((lo)/(-(abc))-(((lo)mod(abc))!=0))-(((hi)&(~(abc)))>>15)*((-(lo))/(abc)-(((lo)mod(abc))!=0))+(((hi)&(abc))>>15)*(-(lo))/(-(abc)); 3:10      hi lo abc fm/mod
    ; seconds: 0           ;[ 8:42]
    dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'PUSH(hi,lo,abc) SMDIVREM'
    
      .warning Pasmo does not support 32 bit numbers and M4 does not know all values(They can only emulate 28-bit/12-bit or 16-bit/16-bit without checking the range): "hi<<16+lo abc sm/rem"
                            ;[8:42]     hi lo abc sm/rem   ( -- +(((((((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)+((hi)>>15?-(lo):lo) mod (((abc)>>15)?-(abc):abc))mod (((abc)>>15)?-(abc):abc))xor((hi)>>15*(-1)))+((hi)>>15) +(((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)/(((abc)>>15)?-(abc):abc)<<12+((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<4>>12)/(((abc)>>15)?-(abc):abc)<<8+(((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<4>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<8>>12)/(((abc)>>15)?-(abc):abc)<<4+((((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<4>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<8>>12)mod (((abc)>>15)?-(abc):abc)<<4+(15& ((hi)>>15?-(lo):lo)))/(((abc)>>15)?-(abc):abc))xor(((hi) xor (abc))>>15*(-1)))+(((hi) xor (abc))>>15) )
        push DE             ; 1:11      hi lo abc sm/rem
        push HL             ; 1:11      hi lo abc sm/rem
        ld   DE, +(((((((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)<<4)mod (((abc)>>15)?-(abc):abc)+((hi)>>15?-(lo):lo) mod (((abc)>>15)?-(abc):abc))mod (((abc)>>15)?-(abc):abc))xor((hi)>>15*(-1)))+((hi)>>15); 3:10      hi lo abc sm/rem
        ld   HL, +(((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)/(((abc)>>15)?-(abc):abc)<<12+((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<4>>12)/(((abc)>>15)?-(abc):abc)<<8+(((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<4>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<8>>12)/(((abc)>>15)?-(abc):abc)<<4+((((((hi)>>15?~((hi)+((lo)=0)):hi) mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<4>>12)mod (((abc)>>15)?-(abc):abc)<<4+((hi)>>15?-(lo):lo)<<8>>12)mod (((abc)>>15)?-(abc):abc)<<4+(15& ((hi)>>15?-(lo):lo)))/(((abc)>>15)?-(abc):abc))xor(((hi) xor (abc))>>15*(-1)))+(((hi) xor (abc))>>15); 3:10      hi lo abc sm/rem
    ; seconds: 0           ;[ 8:42]

    Popravde to byla docela dobra vyzva co vsechno tim jde udelat.

    3. 5. 2023, 02:40 editováno autorem komentáře

  • 3. 5. 2023 2:13

    _dw

    Na jp (ix) a jp (iy) jsem uplne zapomnel!
    Zda se ze automaticky preferuji jednobajtove instrukce, protoze bez IX se jde vetsinou obejit.
    Ten kod jsem psal narychlo nez jsem bezel do prace a cestou me napadlo, ze tam vubec nemusim pouzivat stinove registry, zvlast v ROMce, kde to spis prepinam zase zpet a ze bych mel uchovavat ten pouzity registr a s ex (sp),hl to dokonce bude i kratsi!

    original

    ld   (jump_address), a   ; 3:13   uložíme offset do tohoto paměťového místa
    jr   $                   ; 2:12   relativní skok přečte offset z ^
                             ;[5:25]

    stinovy a niceny BC

          exx                      ; 1:4
          add  a, low repeat       ; 2:7
          ld   c, a                ; 1:4
    if ((0xFF & repeat) >= (256-2*16))
          adc  a, high repeat      ; 2:7
          sub  c                   ; 1:4
          ld   b, a                ; 1:4
    else
          ld   b, high repeat      ; 2:7
    endif
          push bc                  ; 1:11    menit stinove BC je bezpecne pro navrat do basicu
          exx                      ; 1:4
          ret                      ; 1:10
                                   ;[9:47]
                                  ;[11:55]

    niceny IX (pouzivam instrukce co umi originalni ZX, ale ne vsechny Z80 klony, slo by to resit i jinak mozna i rychleji, ale nechce se me v tehle variante moc vrtat)

          add  a, low repeat       ; 2:7
          ld   ixl, a              ; 2:8
    if ((0xFF & repeat) >= (256-2*16))
          adc  a, high repeat      ; 2:7
          sub  ixl                 ; 2:8
          ld   ixh, a              ; 2:8
    else
          ld   ixh, high repeat    ; 3:11
    endif
          jp  (ix)                 ; 2:8    menit stinove BC je bezpecne pro navrat do basicu
                                   ;[9:34]
                                  ;[12:46]

    Moje volba by byla pouzit zasobnik a ex (sp),hl. Kratke ale pomalejsi.

          push hl                  ; 1:11
          add  a, low repeat       ; 2:7
          ld   l, a                ; 1:4
    if ((0xFF & repeat) >= (256-2*16))
          adc  a, high repeat      ; 2:7
          sub  l                   ; 1:4
          ld   h, a                ; 1:4
    else
          ld   h, high repeat      ; 2:7
    endif
          ex (sp),hl               ; 1:19
          ret                      ; 1:10
                                   ;[8:58]
                                  ;[10:66]

    A jeste jedna varianta do poctu. Jen kdyz je rozbalene LDI mimo predel "segmentu". Navic tahle by vyzadovala inicializaci (zapsani 2 bajtu), takze dalsi takty a bajty.

            add  a, low repeat       ; 2:7
            ld   (in_ram+1), a       ; 3:13
      if ((0xFF & repeat) >= (256-2*16))
            .error ldi deli 256 segment!
      endif
            jp   in_ram              ; 3:10
                                    ;[11:40]
    ...
    in_ram:
            jp repeat                ; 3:10