The Red Man
Messages postés111Date d'inscriptionvendredi 15 avril 2005StatutMembreDernière intervention13 juin 2010
-
17 févr. 2009 à 21:24
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019
-
22 févr. 2009 à 10:57
je suis completement new in ASM :
J'aimerai savoir je pourrai traduire ce bout de C en ASM, j'ai essayé déjà ça compile pas avec :
include "win32ax.inc"
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="ProgId" content="PowerPoint.Slide" /><meta name="Generator" content="Microsoft PowerPoint 12" />;=================================================
; TP 0 : Translation C program To ASM using FASM;;int i 0;
;int n = 10;
;int s = 0;
;while (i < n){
; if (i%2){
; s += i;
; }
; i++;
;}
pop ebx ; on recupere n=10
cmp ebx, eax ; cmp i & n
push ebx ; on sauvegarde les valeurs n=10
push eax ; i=0
jnl WHILE_LOOP ; while (i<n) <=> if i != n
invoke ExitProcess, 0
;=======================
; While...
;=======================
WHILE_LOOP:
pop eax ; on recupere i=0
mov ebx, eax ; on copie la valeur de eax dans ebx => eax = ebx = 0
push ebx ; on place la ebx = 0 dans la pile
mov ebx, 2
idiv eax ; division entiere (euclidienne) par 2, le quotient : AL et le reste : AH (i/2)
cmp eah, 0 ; on cmp le reste de la division par 0 <=> cmp i%2 & 0
je IF_OK ; if i%2 == 0
;=======================
; If...
;=======================
IF_OK:
pop eax ; on reucpere la valeur de i=0
pop ebx ; on recupere n=10
pop ecx ; on recupere s=0
add ecx, eax ; on ajoute la valeur d'eax (i) dans ecx (s) <=> s+=i
push ecx ; on sauvegarde ecx (s)
inc eax ; on incrémente eax <=> i++
cmp eax, ebx ; compare eax et ebx <=> i & n
push ebx ; on sauvegarde la valeur n=10
push eax ; on sauvegarde la valeur de i=i+1
je WHILE_LOOP ; if i < n => go to WHILE_LOOP
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 21 févr. 2009 à 22:11
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);