BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 5 janv. 2008 à 02:31
GetDC() doit se libérer par ReleaseDC().
Gdi() retourne ce qui sort de CreateCompatibleDC(), l'appelant doit appeler DeleteDC().
__fastcall int setpix(int x,int y,color c) {
UINT add;
if(x<0 || y<0 || x>=X || y>=Y) return 0;
add = 3 *((Y - y - 1) * X + x);
_asm {
mov edi,VIDEO
add edi,add
mov ax,word ptr c
mov [edi],ax
mov al,c.r
mov [edi+2],al
}
return 1;
}
Typique ce qu'il ne faut jamais faire, une fonction se fait full asm ou C mais jamais un peu d'asm au milieu. Rien de tel pour empêcher toute optimisation du compilo.
'return xx' met une valeur dans EAX, vu que tu retournes 0 ou !=0, ce que tu as mis dans EDI allait dans EAX et le retour était deja prêt. Utiliser EDI n'est pas gratuit, le compilo mettra du PUSH et POP pour le restaurer, certain que c'était nécessaire ? (je t'assure que non).
avec
#define X 800
#define Y 600
Une struct se passant par adresse, on dira que color est un simple DWORD (ce qu'il faudrait mettre en union dans la struct color) vu que tu ne fais que le lire.
typedef struct _color {
union _clr {
struct {
BYTE b;
BYTE g;
BYTE r;
BYTE a;
};
DWORD value;
} clr;
} color, *LPcolor;
color c;
v = bnSetpix(x, y, c.clr.value);
Ainsi la fonction n'a pas à déréférencer l'adresse pour accéder à la valeur.
On va se dispenser des tests < 0, suffit de regarder x et y en DWORDs.
__declspec(naked) int __fastcall bnSetpix(int x, int y, DWORD c)
{
__asm {
xor eax, eax
cmp ecx, X
jae short setpixEXIT ;// x >= X
cmp edx, Y
jae short setpixEXIT ;// y >= Y
mov eax, edx
neg eax
add eax, (Y - 1)
imul eax, X
add eax, ecx
mov dx, word ptr[esp+4]
lea eax, [eax+eax*2]
add eax, VIDEO
mov cl, byte ptr[esp+6]
mov word ptr[eax], dx
mov byte ptr[eax+2], cl
setpixEXIT:
ret 4
}
}
Voici ce qu'il convenait d'écrire, tu constateras qu'il n'y a pas de PUSH ni de POP, les 3 registres généraux suffisaient amplement.
Pour conclure: Si l'ASM reste la voie de l'optimisation maximale, sa mise en oeuvre nécessite de nombreuses heures de pratique. Je t'encourage bien entendu à persévérer mais retiens bien que ce doit être FULL ASM ou FULL C, jamais de mix. C'est à force d'exercices qu'on prend la tournure d'esprit ASM mais il convient de ne pas en insérer dans ses codes tant qu'on n'en a pas une habitude bien rodée, exercices d'abord, en prod ensuite.
5 janv. 2008 à 02:31
Gdi() retourne ce qui sort de CreateCompatibleDC(), l'appelant doit appeler DeleteDC().
__fastcall int setpix(int x,int y,color c) {
UINT add;
if(x<0 || y<0 || x>=X || y>=Y) return 0;
add = 3 *((Y - y - 1) * X + x);
_asm {
mov edi,VIDEO
add edi,add
mov ax,word ptr c
mov [edi],ax
mov al,c.r
mov [edi+2],al
}
return 1;
}
Typique ce qu'il ne faut jamais faire, une fonction se fait full asm ou C mais jamais un peu d'asm au milieu. Rien de tel pour empêcher toute optimisation du compilo.
'return xx' met une valeur dans EAX, vu que tu retournes 0 ou !=0, ce que tu as mis dans EDI allait dans EAX et le retour était deja prêt. Utiliser EDI n'est pas gratuit, le compilo mettra du PUSH et POP pour le restaurer, certain que c'était nécessaire ? (je t'assure que non).
avec
#define X 800
#define Y 600
Une struct se passant par adresse, on dira que color est un simple DWORD (ce qu'il faudrait mettre en union dans la struct color) vu que tu ne fais que le lire.
typedef struct _color {
union _clr {
struct {
BYTE b;
BYTE g;
BYTE r;
BYTE a;
};
DWORD value;
} clr;
} color, *LPcolor;
color c;
v = bnSetpix(x, y, c.clr.value);
Ainsi la fonction n'a pas à déréférencer l'adresse pour accéder à la valeur.
On va se dispenser des tests < 0, suffit de regarder x et y en DWORDs.
__declspec(naked) int __fastcall bnSetpix(int x, int y, DWORD c)
{
__asm {
xor eax, eax
cmp ecx, X
jae short setpixEXIT ;// x >= X
cmp edx, Y
jae short setpixEXIT ;// y >= Y
mov eax, edx
neg eax
add eax, (Y - 1)
imul eax, X
add eax, ecx
mov dx, word ptr[esp+4]
lea eax, [eax+eax*2]
add eax, VIDEO
mov cl, byte ptr[esp+6]
mov word ptr[eax], dx
mov byte ptr[eax+2], cl
setpixEXIT:
ret 4
}
}
Voici ce qu'il convenait d'écrire, tu constateras qu'il n'y a pas de PUSH ni de POP, les 3 registres généraux suffisaient amplement.
Pour conclure: Si l'ASM reste la voie de l'optimisation maximale, sa mise en oeuvre nécessite de nombreuses heures de pratique. Je t'encourage bien entendu à persévérer mais retiens bien que ce doit être FULL ASM ou FULL C, jamais de mix. C'est à force d'exercices qu'on prend la tournure d'esprit ASM mais il convient de ne pas en insérer dans ses codes tant qu'on n'en a pas une habitude bien rodée, exercices d'abord, en prod ensuite.
Bonne continuation.