[FASM]Traduction program C to ASM

The Red Man Messages postés 111 Date d'inscription vendredi 15 avril 2005 Statut Membre Dernière intervention 13 juin 2010 - 17 févr. 2009 à 21:24
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 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++;
;}

include "win32ax.inc"

entry start

section ".text" code readable executable
start:
        mov eax, 0              ; s = 0
        push eax
        mov eax, 10             ; n = 10
        push eax
        mov eax, 0              ; i = 0

        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

section '.idata' data readable import
        library kernel32, 'kernel32.dll'
        import kernel32, ExitProcess, 'ExitProcess'

ça serai cool merci !

3 réponses

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 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);
 
  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++
0
The Red Man Messages postés 111 Date d'inscription vendredi 15 avril 2005 Statut Membre Dernière intervention 13 juin 2010 2
22 févr. 2009 à 02:18
Ah merci beaucoup ! C'est beaucoup plus clair maintenant. Maintenant faut tester tout ça.
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
22 févr. 2009 à 10:57
OUPS,
rectif après nuit de sommeil.

Il faut lire:
"Simple test sur le 1er bit ..."
et non "Simple test sur le dernier bit ..."

ciao...
BruNews, MVP VC++
0
Rejoignez-nous