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_movw_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_movl_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.