IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Insérer de l'assembleur dans Lazarus


Sujet :

Lazarus Pascal

  1. #1
    Membre du Club

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Points : 62
    Points
    62
    Billets dans le blog
    1
    Par défaut Insérer de l'assembleur dans Lazarus
    Bonjour,
    J'utilisais Delphi et j'essaie d'utiliser maintenant Lazarus. Dans Delphi, je savais insérer directement de l'assembleur en commençant par asm.
    Cela génère une erreur dans Lazarus.
    Y a-t-il une solution ?
    merci

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    Bonjour, je lis ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      //This is required with Lazarus on x86:
      {$ASMMODE intel}
    Est-ce une piste ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 725
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 725
    Points : 15 124
    Points
    15 124
    Par défaut
    Bonjour,

    pour compléter ce que dit tourlourou (), je donne une fonction complète :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Swap32_si_Moto(C : Cardinal) : Cardinal;
    var
     S : Cardinal;
    begin
      {$ASMMODE intel} // nécessaire si pas {$mode delphi} + couple begin/end
      asm
        bswap EAX // C est passé dans EAX et bswap échange les octets 0123 -> 3210
        mov   S, EAX
      end;
      if Motorola then Result := S else Result := C;
    end;
    et je rajoute
    Citation Envoyé par GerardJ Voir le message
    Cela génère une erreur dans Lazarus.
    qu'une bonne pratique sur les forums consiste à donner l'erreur, sinon on perd du temps à poser la question "et c'est quoi l'erreur ?" puis à attendre la réponse, ici ça allait, c'était facile.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  4. #4
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Bonjour

    Il y a deux methodes pour utiliser l'assembleur

    Comme l'ont dit mes compères :
    Tu places la directive

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Unit Unit1;
     
    {$mode objfpc}{$H+} 
    {$asmmode intel} // si non par defaut c'est le mode ATT&T. Voir aussi dans les options du projet
     
    Interface
    1) Tu souhaites imbriquer de l'assembleur dans du code natif

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure DoSomething;
    var
     i: integer
    begin
      for i:= 0 to 9 do
      begin
        asm
           // ton code asm ici
        end;
      end;
    end;
    2) Tu souhaites créer une procedure ou fonction entièrement en assembleur
    Il faut alors utiliser le mot clef assembler

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function doSomething : byte; assembler;
    asm
      // ton code assembleur ici
    end;
     
    procedure doSomething; assembler;
    asm
      // ton code assembleur ici
    end;
    voir :
    https://wiki.freepascal.org/Asm
    https://wiki.freepascal.org/Assembler_and_ABI_Resources

    Tu disposes en plus du mot clef assembler de : Register, nostackframe et vectorcall ce dernier étant dispo uniquement à partir de FPC 3.2 et uniquement pour Windows et les instructions SIMD

    exemple :

    pour Windows et avec FPC 3.0.4

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function TBZVector4f.DivideBy2:TBZVector4f;assembler; nostackframe; register;
    asm
      movaps xmm0,[RCX]
      mulps xmm0, XMMWORD PTR [RIP+cHalfOneVector4f]
      movaps [RESULT],xmm0
    end;
    pour Windows et avec FPC 3.2 (non testé)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function TBZVector4f.DivideBy2:TBZVector4f;assembler; vectorcall;
    asm
      mulps xmm0, XMMWORD PTR [RIP+cHalfOneVector4f]
      movaps [RESULT],xmm0 
    end;
    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  5. #5
    Membre du Club

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Points : 62
    Points
    62
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Bonjour,

    pour compléter ce que dit tourlourou (), je donne une fonction complète :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Swap32_si_Moto(C : Cardinal) : Cardinal;
    var
     S : Cardinal;
    begin
      {$ASMMODE intel} // nécessaire si pas {$mode delphi} + couple begin/end
      asm
        bswap EAX // C est passé dans EAX et bswap échange les octets 0123 -> 3210
        mov   S, EAX
      end;
      if Motorola then Result := S else Result := C;
    end;
    et je rajoute

    qu'une bonne pratique sur les forums consiste à donner l'erreur, sinon on perd du temps à poser la question "et c'est quoi l'erreur ?" puis à attendre la réponse, ici ça allait, c'était facile.
    Merci ça marche sauf que cela génère une erreur que je n'ai pas dans Delphi...
    joueur.pas(391,8) Error: Asm: [push reg32] invalid combination of opcode and operands
    le code :
    Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
            MOV  EAX, Substr
            MOV  EDX, S
            MOV  ECX, &Offset
           test  eax, eax
           jz    @Nil
           test  edx, edx
           jz    @Nil
           dec   ecx
           jl    @Nil
     
           push  esi
           push  ebx
     
           mov   esi, [edx-4]  //Length(Str)
           mov   ebx, [eax-4]  //Length(Substr)
           sub   esi, ecx      //effective length of Str
           add   edx, ecx      //addr of the first char at starting position
           cmp   esi, ebx
           jl    @Past         //jump if EffectiveLength(Str)<Length(Substr)
           test  ebx, ebx
           jle   @Past         //jump if Length(Substr)<=0
     
           add   esp, -12
           add   ebx, -1       //Length(Substr)-1
           add   esi, edx      //addr of the terminator
           add   edx, ebx      //addr of the last char at starting position
           mov   [esp+8], esi  //save addr of the terminator
           add   eax, ebx      //addr of the last char of Substr
           sub   ecx, edx      //-@Str[Length(Substr)]
           neg   ebx           //-(Length(Substr)-1)
           mov   [esp+4], ecx  //save -@Str[Length(Substr)]
           mov   [esp], ebx    //save -(Length(Substr)-1)
           movzx ecx, byte ptr [eax] //the last char of Substr
     
    @Loop:
           cmp   cl, [edx]
           jz    @Test0
           jmp   @Exit
    @AfterTest0:
           cmp   cl, [edx+1]
           jz    @TestT
    @AfterTestT:
           add   edx, 4
           cmp   edx, [esp+8]
           jb   @Continue
    @EndLoop:
           add   edx, -2
           cmp   edx, [esp+8]
           jb    @Loop
    @Exit:
           add   esp, 12
    @Past:
           pop   ebx
           pop   esi
    @Nil:
           xor   eax, eax
           //ret
           jmp  @Fin
    @Continue:
           cmp   cl, [edx-2]
           jz    @Test2
           cmp   cl, [edx-1]
           jnz   @Loop
    @Test1:
           add   edx,  1
    @Test2:
           add   edx, -2
    @Test0:
           add   edx, -1
    @TestT:
           mov   esi, [esp]
           test  esi, esi
           jz    @Found
    @String:
           movzx ebx, word ptr [esi+eax]
           cmp   bx, word ptr [esi+edx+1]
           jnz   @Exit
           cmp   esi, -2
           jge   @Found
           movzx ebx, word ptr [esi+eax+2]
           cmp   bx, word ptr [esi+edx+3]
           jnz   @Exit
           add   esi, 4
           jl    @String
    @Found:
           mov   eax, [esp+4]
           add   edx, 2
     
           cmp   edx, [esp+8]
           ja    @Exit
     
           add   esp, 12
           add   eax, edx
           pop   ebx
           pop   esi
    @Fin:

  6. #6
    Membre du Club

    Inscrit en
    Novembre 2008
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 69
    Points : 62
    Points
    62
    Billets dans le blog
    1
    Par défaut
    Ce sont les lignes 12 et 13 (push esi et push ebx) et les lignes pop correspondantes....

  7. #7
    Membre éclairé

    Homme Profil pro
    Rédacteur technique (retraité)
    Inscrit en
    Octobre 2009
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 81
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Rédacteur technique (retraité)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 168
    Points : 807
    Points
    807
    Par défaut
    Bonjour GerardJ,

    Si tu compile pour une plateforme cible 64bits il est possible que tu ne puisse pas PUSHer/POPer des registres 32 bits, ce qui correspondrait bien au message d'erreur constaté.

    Essai de PUSHer/POPer RSI et RBX au lieu de ESI et EBX.

  8. #8
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 937
    Points : 59 415
    Points
    59 415
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    Citation Envoyé par DomDA91 Voir le message
    Si tu compile pour une plateforme cible 64bits il est possible que tu ne puisse pas PUSHer/POPer des registres 32 bits, ce qui correspondrait bien au message d'erreur constaté.

    Essai de PUSHer/POPer RSI et RBX au lieu de ESI et EBX.
    Exactement, en 64 bits il est possible de pusher des registres 64 bits et 16 bits (moyennant préfixe) mais pas 32 bits.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  9. #9
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 325
    Points : 4 141
    Points
    4 141
    Par défaut 32 et 64 sont dans un bateau
    Bonjour,

    D'autres différences existent entre 32 et 64 bits comme l'usage des registres pour passer les arguments (il est préférable d'inciter explicitement le compilateur à utiliser les registres plutôt que la pile en ajoutant noframestack).

    Ainsi l'exemple swap sur intel passera effectivement l'argument dans eax en 32 bits mais pas dans rax en 64 bits (plutôt rdx). Ça n'aide pas la portabilité mais je crois que c'est pour respecter la convention de fastcall.

    Remarque : la multiplication du nombre de registres en 64 bits permet souvent d'éviter (ou de limiter) empilages et dépilages (push/pop) qui ne sont pas neutres en temps, surtout pour des fonctions courtes. Dans l'exemple, on peut ainsi remplacer esi et ebx par r10d et r11d et gagner ainsi 4 opérations push/pop.

    Toujours pour les fonctions/procédures courtes. Il faut éviter d'utiliser l'assembleur pour des opérations accessibles simplement au langage. En effet, un code standard autorisera un inline (inopérant avec du code assembleur) qui permettra au compilateur d'éviter tout appel/retour de fonction et lui laissera le loisir de jongler avec les registres (alors que l'assembleur fixe les registres utilisés). Bien sûr, il en est autrement si l'opération nécessite beaucoup plus de code Pascal que de code assembleur (si si ça existe): exemple popcnt qui compte le nombre de bits à 1 d'un registre.

    L'optimisation est un sport de combat

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  10. #10
    Membre éclairé

    Homme Profil pro
    Rédacteur technique (retraité)
    Inscrit en
    Octobre 2009
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 81
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Rédacteur technique (retraité)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 168
    Points : 807
    Points
    807
    Par défaut
    Bonjour,

    GerardJ ne répond plus ? L'aurions-nous découragé, ce serait dommage !

    Je me souviens maintenant avoir conversé (içi) avec lui il y a plus de trois ans à propos d'un code assembleur très proche de celui qu'il nous soumet maintenant.
    Il est vrai qu'à l'époque nous n'avions envisagé qu'un contexte Delphi/32 bits et il est, depuis, coulé beaucoup d'eau sous les ponts, notamment la sortie de Lazarus 64bits et la généralisation des plateformes 64 bits.

    Je présume qu'il cherche maintenant, pour évaluer l'environnement FPC/Lazarus, à recompiler son projet tel-quel.

    Dans ce but, ce que l'on pourrait lui proposer dans un premier temps c'est des tenter de refaire l'essai mais en indiquant à Lazarus de compiler un exécutable 32bits (et non 64bit ce qu'il fait par défaut).

    Il faut pour cela installer le cross-compilateur FPC/32bits. Cette discussion récente explique comment faire.

  11. #11
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Bonjour

    Concernant l'optimisation de la fonction "pos", allez voir, cette discussion, intéressante dans le forum Delphi, avec en primes, quelques fonctions en ASM.

    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

Discussions similaires

  1. [Lazarus] Assembleur dans Lazarus sous Ubuntu
    Par pedestre dans le forum Lazarus
    Réponses: 1
    Dernier message: 30/01/2014, 20h59
  2. [Lazarus] Assembleur dans Lazarus ?
    Par Chin Tao dans le forum Lazarus
    Réponses: 2
    Dernier message: 13/09/2007, 10h22
  3. [CR] insérer une image paramétrer dans une étiquette
    Par yoyothebest dans le forum SAP Crystal Reports
    Réponses: 6
    Dernier message: 22/08/2004, 11h58
  4. EDI pour intégrer efficacement de l'assembleur dans du C/C++
    Par Selenite dans le forum Choisir un environnement de développement
    Réponses: 2
    Dernier message: 04/04/2004, 18h27
  5. Comment insérer de l'unicode dans un Richedit ?
    Par DanaKil dans le forum C++Builder
    Réponses: 6
    Dernier message: 30/03/2004, 00h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo