Programmation Delphi & Assembleur



ENGLISH Version
ZONE DE TELECHARGEMENT : FIN DE PAGE - PHOTO D'ECRAN : MILIEU DE PAGE

NEW:
Dernière Mise à Jour le 17/10/2001 # VERSION 1.7 #
La version 2.0.0 de DIBUltra est en cours d'écriture
On y trouvera entre autre :
La gestion des sprites.
De multiples transitions entre 2 DIBs.
Une gestion des masques plus puissantes.
Des surprises... ;-)

Il existe de nombreux sites consacrés à DELPHI mais je n'en connais pas qui exploitent la vrai puissance du compilateur en parlant de la programmation ASSEMBLEUR sous Delphi 2, 3 4, 5, 6 et Kylix (...).

Aussi, je vais tenter cette approche en mettant à votre disposition une unité graphique encapsulant les DIB et effectuant diverses opérations. Cette unité est en cours de développement mais donne déjà des résultats appréciables. Il est important de souligner son aspect pédagogique car on peut trouver dans le sources une masse très importante de commentaires et explications en tout genre.(Ce qui n'en fait pas moins une unité puissante !)

Cet unité s'adresse néanmoins à des personnes connaissant un peu l'assembleur. Si ce n'est pas votre cas, surfez un peu aux rubriques "assembleur" des moteurs de recherche pour avoir les bases et la connaissance minimum de la chose.
(disons que ça y est, vous avez lu et compris une dizaine de pages sur le sujet).
Pour mémento, vous trouverez ici un abécédaire des instructions assembleurs 80x86 (Il n'est pas de moi mais de Gael LE MAHEC). Pour programmer sérieusement il faut avoir le manuel technique (format PDF) dispensé par Intel. Cependant en attendant qu'Intel me permette de délivrer en ligne son manuel, je vous suggère d'aller le récupérer à sa source.
Grace au compilateur Delphi ou C++Builder, vous avez à tout moment la possibiliter de basculer en mode ASM en tapant :

asm
... vos instructions assembleur ...
end;
Bien sûr, il y a certaines conventions à respecter (EBX à sauver, etc...) mais je vous laisse lire Delphi.hlp pour cela. Dans vos programmes, lorsque une zone est une boucle parcourue de nombreuses fois (ex: un million de fois pour traiter les pixels d'une image par exemple), il peut être judicieux de la traduire en assembleur. Evidemment, traduire tout son programme en assembleur relève de la gageure et de l'inutilité la plus totale ! Sachez donc bien cibler la zone critique et essayer de faire mieux que le compilo ! (cette dernière remarque n'étant pas à prendre à la légère)

Quoi qu'il en soit, ne vous inquiétez pas, l'assembleur ça n'est pas très difficile et Delphi nous facilite la vie (utilisation des variables, des records, des procedures, etc... définis dans les parties Pascal du programme) mais pour vous rassurer voici trois extraits du code source. Remarquez la somme de commentaires ; mais n'essayez pas de le comprendre hors de son contexte ;-)



@LINEHORZT24BITS:
    // Tracé de la ligne horizontale
    MOV  EAX, Coul
    MOV  EBX, CoulTmp     // Permutation temporaire avec la couleur Rouge
  @RepeatLNX24:
      ROL  MASQUE, 1      // Boucle Repeat
      JNC  @LNX24NOTRACE  //   If PlotON Then Begin
      MOV  [EDI + 0], AL  //     PxB^[Pt] := CoulB; <--- [Mem] <= AL (8 bits)
      MOV  [EDI + 1], AH  //     PxB^[Pt] := CoulV; <--- [Mem] <= AH (8 bits)
      MOV  [EDI + 2], BL  //     PxB^[Pt] := CoulR; <--- [Mem] <= DH (8 bits)
    @LNX24NOTRACE:        //   End Else ;                           ----------
      ADD  EDI, AdXPlus   //   Inc(Pt,AdXPlus);                     = 24 bits
      SUB  ECX, PasX      //   Dec(dx, PasX)
      JNZ  @RepeatLNX24   //   Until (dx=0);
      MOV  EBX, PasY
      ADD  EDI, AdYPlus   // Inc(Pt,AdYPlus)
    RET




    // Pendant la double indirection, on calcule :
    //   Seg.dy := Seg.y2 - Seg.y1;
    //   Seg.dx := Seg.x2 - Seg.x1;
    // Cela supprime la dépendance de données entre les instructions
    // de l'indirection et évite les cycles de freeze du pipeline du
    // processeur (type Pentium et successeur x86)
    MOV ECX,    Seg.y2 {Calcul de Seg.dy}
    LEA EAX,    [EAX * 1 + @Table1] // Double Indirection : premier niveau
    SUB ECX,    Seg.y1 {Calcul de Seg.dy}
    MOVZX EAX,  BYTE PTR [EAX]      // Double Indirection : Récupération du N de On N Goto
    MOV Seg.dy, ECX   {Calcul de Seg.dy}
    LEA EAX,    [EAX * 4 + @Table2] // Double Indirection : premier niveau
    MOV ECX,    Seg.x2 {Calcul de Seg.dx}
    MOV EAX,    [EAX]               // Prepare to JUMP
    SUB ECX,    Seg.x1 {Calcul de Seg.dx}
    MOV Seg.&dy,ECX    {Calcul de Seg.dx}
    JMP EAX                         // GO ! : On X Goto n1,n2,n3,n4,n5...

    procedure TDIBUltra.RotateStyle (n : Byte); assembler;
    asm    // "Rotate" le masque (n Modulo 32) fois
      MOV  CL, n
      ROL  [Self].Mask, CL
    End;

    function  TDIBUltra.PlotON : Boolean; assembler;
    asm
      MOV  Result, True
      ROL  [Self].Mask, 1
      JC   @End
      MOV  Result, False
    @End:
    End;

    procedure TDIBUltra.PrepareStyle; assembler;
    asm    // Rotate le masque jusqu'à présenter un point imprimable
      MOV  EAX, [Self].Mask
      BSR  ECX, EAX
      SUB  ECX, 31
      NEG  ECX
      ROL  [Self].Mask, CL
    End;

EXTENSION de DIBUltra :

Parce que de nombreuses fonctionnalités de cette bibliothèque évitent d'avoir recours aux appels GDI, on peut envisager développer des applications assises uniquement sur ces appels (coté graphisme). Les fonctions de recopie d'image mémoire en mémoire vidéo étant ensuite très proches dans tous les systèmes, il est possible de faire "tourner" une application sous Linux ou Win95 & Co avec une apparence et un comportement similaires !

Testez Kylix Open Edition !!!
DIBUltra n'a pas été testé sous Kylix. Il fonctionnne par contre sous Wine ("émulateur" Win32). DIBUltra 2.x est lui, totalement Linux/Win32.
Quoiqu'il en soit, pour toute information ou réflexion sur cette approche Bi-platteforme, Mailez moi !


Je ne détaillerai pas ici les fonctionnalités de l'unité DIBUltra puisque 7 mini-projets sont fournis avec pour expliquer par l'exemple son utilisation. Bien évidemment toutes les unités sont fournies avec les sources. La licence en vigueur est la GNU Licence.
Disons simplement que DIBUltra permet de tracer des lignes de manière plus rapide le GDI de windows. (la fonction Pixels[x,y]:=ClColor est notamment 10 fois plus rapide) L'unité implémente un style de trait (point, tirets, défini par l'utilisateur...) très souple d'emploi. DIBUltra implémente aussi un format de sauvegarde propriétaire d'images DIB compressées (mais sait aussi lire les Bitmap normales). Enfin la zone de clipping est librement définissable par l'utilisateur qui peut ainsi limiter son tracé. Ce type de Bitmap s'utilisant typiquement hors screen, (en Blit surface), des fonctions de gestion du buffering sont fournies.
La dernière version (1.7) corrige quelques Bugs et apporte le support de la couche Alpha (différentes densités de transparence sont possibles, définissables auparavant grâce à votre éditeur de dessin préféré). Le mode de tracé est définissable (COPY, ANDPEN, ORPEN, XORPEN...) et l'enregistrement des DIBs 24 bpp optimisé. La syntaxe particulière de Delphi 6 est prise en compte !

Lorsque cela a été possible, les méthodes et propriétés de TDIBUltra sont identiques à celles de leurs équivalent TBitmap. Il existe quelques différences (ex Bitmap.Canvas.MoveTo(x,y) devient DIB.MoveTo(x,y) ou encore Bitmap.Canvas.Pen.Color := ClRed devient DIB.PenColor := ClRed ...) mais en règle générale on fait assez rapidement le portage. Enfin il convient de rappeler que cette unité a un object pédagogique et que le code assembleur n'est pas optimisé au mieux (Je pense pouvoir gagner près d'un facteur 2 encore ; en tout cas le code actuel fonctionne bien, c'est toujours cela). A la version 2.0.0 viendra sans doute quelque chose de mieux...
Les 7 mini-applications fournies avec DIBUltra montrent :

AboutBox : - l'utilisation de Pixels[x,y] pour un mouvement rapide
Compress : - l'utilisation des méthodes de chargement d'images sur disque ou en tant que ressource liées dans l'exécutable
Drawing : - l'utilisation du style de pinceau (pointillés, traits...), des couleurs indexées, de ScanLine, du Buffering.
ScreenSplash : - l'apparition tout en fusion d'un screen splash affichant le logo DIBUltra (auto pub!)
SimpleDemo : - la mise en oeuvre minimum de DIBUltra (cela m'a été demandé)
AlphaDemo: - l'utilisation de la fonction AlphaBlit pour afficher une image avec différents niveaux de transparence.
AlphaTool: * Cette appli permet de compiler des images compressées intégrant des infos de couche Alpha. (utile pour jouer à cela)
Quelques photos d'écran pour les curieux :


La AboutBox (A propos) du DRYSIM Project


Idem quelques secondes plus tard...



La fée, irréelle, s'affiche avec certaines
zones très transparentes, d'autres opaques...



Pour mettre en oeuvre la couche Alpha, un petit utilitaire permet
d'assembler les différents fichiers (l'image et son masque).



L'application des méthodes LoadFrom / SaveTo



La fenêtre de traçage des multiples lignes...


Et avec différents styles !


DIBUltra se décompose en 4 unités :

DIBUltra.pas : Noyau de DIBUltra, objet TDIBUltra
DIBtype.pas : Tous les types utilisables s'y trouvent
DIBCodec.pas : Cet unité permet l'encodage et le décodage des fichiers *.udc
DIBFX.pas : Ce fichier est directement inclus ($INCLUDE) dans DIBUltra, il s'agit des effets spéciaux

On remarque très vite l'intérêt de l'assembleur (et des commentaires) dans certains cas, en effet malgré 450 Ko de fichiers source, cette unité compilée ne dépasse pas 55 Ko en dcu (en comptant tous les units).


Bon, assez discuté, passons au téléchargement des unités avec les projets exemples :

DIBUltra (1.3) avec les EXECUTABLES compilées + les SOURCES 780 Ko
DIBUltra (1.7 !!) avec uniquement les SOURCES (non compilées) 313 Ko (mieux non ?)

Bonne lecture et participez à ce projet libre !


Retour.