Názor k článku Hrátky s barvovou paletou a vykreslení jednotlivých pixelů kartou CGA od CHe - divoko, vútorné x-ové slučky vyzerajú takto: frame_copy_movb() 0000351D 8B1EB006...

  • Článek je starý, nové názory již nelze přidávat.
  • 14. 7. 2024 22:17

    CHe

    divoko, vútorné x-ové slučky vyzerajú takto:

    frame_copy_movb()

    0000351D  8B1EB006          mov bx,[0x6b0]
    00003521  8A00              mov al,[bx+si]
    00003523  C41EAB00          les bx,[0xab]
    00003527  268801            mov [es:bx+di],al
    0000352A  46                inc si
    0000352B  47                inc di
    0000352C  FE46FF            inc byte [bp-0x1]
    0000352F  807EFF50          cmp byte [bp-0x1],0x50
    00003533  72E8              jc 0x351d

    frame_copy_mov­w_near()

    0000367D  8BC6              mov ax,si
    0000367F  D1E0              shl ax,1
    00003681  8B1EB006          mov bx,[0x6b0]
    00003685  03D8              add bx,ax
    00003687  8B07              mov ax,[bx]
    00003689  8BD7              mov dx,di
    0000368B  D1E2              shl dx,1
    0000368D  8B1EAB00          mov bx,[0xab]
    00003691  03DA              add bx,dx
    00003693  268907            mov [es:bx],ax
    00003696  46                inc si
    00003697  47                inc di
    00003698  FE46FF            inc byte [bp-0x1]
    0000369B  807EFF28          cmp byte [bp-0x1],0x28
    0000369F  72DC              jc 0x367d

    frame_copy_mo­vl_near() je už úplná divočina s 25 inštr. a plejádou push/pop v každej it. (aj tak je ale o chlp rýchlejší než ten movw, keďže presunie 32b na it.)

    a hej, keď sa array indexovanie nahradí čisto ptr aritmetikou:

    void frame_copy_movw_near_ptr() {
      unsigned char x, y, b;
      unsigned int _es *screen_p;
      unsigned int *buf_p;
    
      _ES = FP_SEG(screen);
      for (b = 0; b < SCR_BANKS; b++) {
        screen_p = &screen[b * SCR_BANK_OFFSET];
        buf_p = &buf[b * SCR_LINE_OFFSET];
        for (y = 0; y < SCR_H / SCR_BANKS; y++) {
          for (x = 0; x < SCR_LINE_OFFSET / 2; x++) {
            *screen_p++ = *buf_p++;
          }
          buf_p += SCR_LINE_OFFSET / 2;  // skip even/odd line of src
        }
      }
    }

    vedie to k relatívne decentnému výsledku:

    000036FC  8B04              mov ax,[si]
    000036FE  268905            mov [es:di],ax
    00003701  83C602            add si,byte +0x2
    00003704  83C702            add di,byte +0x2
    00003707  FE46FF            inc byte [bp-0x1]
    0000370A  807EFF28          cmp byte [bp-0x1],0x28
    0000370E  72EC              jc 0x36fc

    škoda akurát tej loop premennej v stack frame namiesto registra a add si/di, 8b neviem či je optimálnejšie než 2x inc

    Nie som teraz pri tom Amstrade, no v DOSBoxe je toto zhruba 1,7-krát efektívnejšie než najrýchlejší z tých array index prístupov.