On ne "traduit" pas littéralemebnt du C en ASM, on doit le repenser en ASM.
C'est ce que fait un compilo C de manière automatisée mais oh combien très élaborée.
Ton code à transcrire:
int i = 0;
int n = 10;
int s = 0;
while(i < n) {
if(i % 2) s += i;
i++;
}
On va donc commencer le travail par 2 petites réflexions.
1) if(i % 2) nous devons donc vérifier si nbr est pair ou impair.
Hors de question de faire un DIV de 40 cycles pour un truc si bidon.
Simple test ur le dernier bit nous dira la même chose en 1 cycle.
Tout ça pour dire que souvent, même si mal codé comme ici, le compilo C rattrapera en remplaçant par le bon code efficace (eh oui, il le fait).
2) Malheureusement c'est encore une errreur de prog au niveau du C (peut-être voulue si c'est un exercice de class), que le compilo aura certainement aussi rattrapée.
Le 1er tour de boucle ne servirait à rien:
s += i; ferait += 0 donc inutile.
On démarrera donc i à 1 au lieu de 0.
mov eax, 1 ; i = 1
xor edx, edx ; s = 0
whileIinf10:
test eax, 1
je short nextI
add edx, eax
nextI:
inc eax
cmp eax, 10
jne short whileIinf10
Voila pour une 1ere phase ASM correcte, mais loin d'être performante.
Pour l'obtenir, il faut tendre vers 0 tant que faire se peut et ici c'est le cas, on gagnera ainsi 1 CMP par tour de boucle puisque le CPU place EFLAGS sur toute opération arythmétique.
Voici prog en C (fait sur VC++) qui testera tout cela, y compris la version 2 de ASM.
On obtient bien 25 à tout coup.
EXE résultant fait 2.5 Ko, pas de quoi pourrir un disque dur, donc ne pas se priver de tester.
#include <windows.h>
int Original()
{
int i = 0;
int n = 10;
int s = 0;
while(i < n) {
if(i % 2) s += i;
i++;
}
return s;
}
int bnOriginal()
{
int i = 1;
int s = 0;
do {
if(i & 1) s += i;
} while(++i < 10);
return s;
}
__declspec(naked) int __stdcall bnASM()
{
__asm {
mov eax, 1 ; i = 1
xor edx, edx ; s = 0
whileIinf10:
test eax, 1
je short nextI
add edx, eax
nextI:
inc eax
cmp eax, 10
jne short whileIinf10
mov eax, edx
ret 0
}
}
__declspec(naked) int __stdcall bnASM2()
{
__asm {
mov eax, 9 ; i = 9
xor edx, edx ; s = 0
whileIinf10:
test eax, 1
je short nextI
add edx, eax
nextI:
dec eax
jne short whileIinf10
mov eax, edx
ret 0
}
}
void Essayer(VOID)
{
char buf[12];
int R;
R = Original();
ultoa(R, buf, 10);
MessageBox(0, buf, "C", 0);
R = bnOriginal();
ultoa(R, buf, 10);
MessageBox(0, buf, "C revu", 0);
R = bnASM();
ultoa(R, buf, 10);
MessageBox(0, buf, "ASM", 0);
R = bnASM2();
ultoa(R, buf, 10);
MessageBox(0, buf, "ASM optim", 0);
}
#pragma comment(linker, "/entry:myWinMain")
__declspec(naked) void __stdcall myWinMain()
{
__asm {
call Essayer
push 0
call dword ptr ExitProcess
}
}
ciao...
BruNews, MVP VC++