Partage
  • Partager sur Facebook
  • Partager sur Twitter

Constantes du noyau Linux

    20 novembre 2020 à 13:36:45

    Bonjour à tous,

    je me suis mis à la programmation assembleur x86_64 sous Debian 10.6 amd64.

    Il me semble que j'ai besoin de connaître les valeurs de beaucoup de constantes définies dans le noyau Linux.

    Je prends l'exemple de O_CREAT, mais c'est pareil pour O_TRUNC, O_WRONLY ou autres.

    Il faut bien que je donne la valeur de ces constantes à mon programme en assembleur; il ne les connaît pas a priori.

    J'ai cherche partout dans /usr/src les "#define O_CREAT" (par exemple); j'ai trouvé des tas de valeurs différentes.

    Alors, ma question est : où (et comment) dois-je chercher pour trouver la bonne information?

    Je vous remercie infiniment.

    Très cordialement,

    Roland THOMAS.

    • Partager sur Facebook
    • Partager sur Twitter
      20 novembre 2020 à 20:14:04

      RolandThomas2 a écrit:


      J'ai cherche partout dans /usr/src les "#define O_CREAT" (par exemple); j'ai trouvé des tas de valeurs différentes.

      Curieux. Lesquelles ?

      • Partager sur Facebook
      • Partager sur Twitter
        21 novembre 2020 à 8:19:49

        Bonjour,

        je lance la commande :

        $ find /usr/src/ -type f -exec grep "define O_CREAT" {} \;

        J'obtiens :

        #define O_CREAT         00000100        /* not fcntl */
        #define O_CREAT         0x0200  /* not fcntl */
        #define O_CREAT         0x0100  /* not fcntl */
        #define O_CREAT         000000400 /* not fcntl */
        #define O_CREAT          01000  /* not fcntl */
        #define O_CREAT         00000100        /* not fcntl */
        #define O_CREAT         0x0200  /* not fcntl */
        #define O_CREAT         0x0100  /* not fcntl */
        #define O_CREAT         000000400 /* not fcntl */
        #define O_CREAT          01000  /* not fcntl */
        #define O_CREAT         00000100        /* not fcntl */

        etc. (la liste est longue...)

        J'ai trouvé une solution qui résout mon problème mais qui ne me satisfait pas :

        écrire un programme en C qui affiche ces constantes, puisqu'il les connaît.

        Mais ça ne me semble pas normal de procéder ainsi.

        Autre commande intéressante :

        $ locate fcntl.h | wc

            122     122    8262

        Pour info : Linux sophie 4.19.0-12-amd64 #1 SMP Debian 4.19.152-1 (2020-10-18) x86_64 GNU/Linux

        Merci.

        • Partager sur Facebook
        • Partager sur Twitter
          21 novembre 2020 à 10:03:43

          Tout s'explique

          $ rgrep "define O_CREAT" /usr/src
          /usr/src/linux-headers-4.19.0-11-common/include/uapi/asm-generic/fcntl.h:#define O_CREAT		00000100	/* not fcntl */
          /usr/src/linux-headers-4.19.0-11-common/arch/mips/include/uapi/asm/fcntl.h:#define O_CREAT		0x0100	/* not fcntl */
          /usr/src/linux-headers-4.19.0-11-common/arch/sparc/include/uapi/asm/fcntl.h:#define O_CREAT		0x0200	/* not fcntl */
          /usr/src/linux-headers-4.19.0-11-common/arch/alpha/include/uapi/asm/fcntl.h:#define O_CREAT		 01000	/* not fcntl */
          /usr/src/linux-headers-4.19.0-11-common/arch/parisc/include/uapi/asm/fcntl.h:#define O_CREAT		000000400 /* not fcntl */
          /usr/src/linux-headers-4.19.0-12-common/include/uapi/asm-generic/fcntl.h:#define O_CREAT		00000100	/* not fcntl */
          /usr/src/linux-headers-4.19.0-12-common/arch/mips/include/uapi/asm/fcntl.h:#define O_CREAT		0x0100	/* not fcntl */
          /usr/src/linux-headers-4.19.0-12-common/arch/sparc/include/uapi/asm/fcntl.h:#define O_CREAT		0x0200	/* not fcntl */
          /usr/src/linux-headers-4.19.0-12-common/arch/alpha/include/uapi/asm/fcntl.h:#define O_CREAT		 01000	/* not fcntl */
          /usr/src/linux-headers-4.19.0-12-common/arch/parisc/include/uapi/asm/fcntl.h:#define O_CREAT		000000400 /* not fcntl */
          /usr/src/linux-headers-4.19.0-12-common-rt/include/uapi/asm-generic/fcntl.h:#define O_CREAT		00000100	/* not fcntl */
          


          des valeurs différentes... pour des architectures différentes.

          Si on tient à savoir, pour la machine sur laquelle on développe

          #include <stdio.h>
          #include <fcntl.h>
          
          int main() {
          	printf("O_CREAT = 0x%08x\n", O_CREAT);
          }
          

          Execution

          $ ./a.out 
          O_CREAT = 0x00000040
          

          Ou 0100  en octal   (format  "0%o") si on préfère.


          -
          Edité par michelbillaud 21 novembre 2020 à 10:14:31

          • Partager sur Facebook
          • Partager sur Twitter
            21 novembre 2020 à 20:46:02

            bonsoir,

            j'ai essayé par deux fois de répondre, mais à chaque fois que je me connecte, openclassrooms me promet de m'envoyer un message pour confirmer mon inscription et je n'ai jamais rien reçu. Je ne sais pas comment mes deux premiers posts sont passés, je n'ai jamais eu de mot de passe. Par contre, j'ai dû utiliser une nouvelle adresse mail à chaque fois ; il ne m'en reste pas pour la prochane fois.

            Mon dernier message sera pour dire que j'ai bien écrit le même programme en C pour déterminer les valeurs des constantes, d'accord ça marche, mais si le compilateur C est capable de savoir dans quel fichier il doit trouver ses informations, je devrais en être capable aussi. Je ne pense pas que tous les programmeurs en assembleur utilisent cette méthode pour déterminer les constantes, sinon comment auraient fait les concepteurs du compilateur pour le langage C ?

            Merci, au revoir ; je n'ai plus de nouvelle adresse mail pour me connecter.

            Très cordialement.

            • Partager sur Facebook
            • Partager sur Twitter
              21 novembre 2020 à 22:54:14

              Je ne pense pas qu'il y ait tellement d'amateurs pour aller programmer en assembleur des trucs qui requièrent des appels systèmes.

              La programmation en assembleur, ça va être pour des trucs qui font du calcul lourd qu'on essaie d'optimiser à fond. Faut vraiment être sur que ça en vaut la peine, et qu'on fera mieux que le compilateur C. De nos jours, c'est pas gagné.

              Une manière de voir les répertoires dans lesquels sont cherchés les "include"

              $ cpp -v /dev/null -o /dev/null
              Using built-in specs.
              COLLECT_GCC=cpp
              OFFLOAD_TARGET_NAMES=nvptx-none
              OFFLOAD_TARGET_DEFAULT=1
              Target: x86_64-linux-gnu
              Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-6' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
              Thread model: posix
              gcc version 8.3.0 (Debian 8.3.0-6) 
              COLLECT_GCC_OPTIONS='-E' '-v' '-o' '/dev/null' '-mtune=generic' '-march=x86-64'
               /usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu /dev/null -o /dev/null -mtune=generic -march=x86-64
              ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
              ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/include"
              #include "..." search starts here:
              #include <...> search starts here:
               /usr/lib/gcc/x86_64-linux-gnu/8/include
               /usr/local/include
               /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
               /usr/include/x86_64-linux-gnu
               /usr/include
              End of search list.
              COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/
              LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/8/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/8/../../../:/lib/:/usr/lib/
              COLLECT_GCC_OPTIONS='-E' '-v' '-o' '/dev/null' '-mtune=generic' '-march=x86-64'



              -
              Edité par michelbillaud 21 novembre 2020 à 23:03:16

              • Partager sur Facebook
              • Partager sur Twitter
                22 novembre 2020 à 12:08:32

                Merci et bonne journée.

                Très cordialement.

                • Partager sur Facebook
                • Partager sur Twitter
                  24 novembre 2020 à 16:30:43

                  pour ton problème de mot de passe pour le forum, tu as regardé dans ton dossier des indésirables/spams de tes boites aux lettres (sinon contact un modérateur)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    28 novembre 2020 à 7:33:01

                    Bonjour,

                    mon problème de mot de passe est résolu. Les messages partaient dans les indésirables, en effet, mais par une décision d'Orange qui les marquait comme spam.

                    Bonne journée, merci.

                    R. Thomas.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      29 novembre 2020 à 18:20:28

                      Bonsoir.

                      Pour Michel Billaud : si si il y a des fous qui ne programment qu'en assembleur et donc qui font appel à des fonctions système pour afficher, lire écrire dans des fichiers, lancer des threads, utiliser le tas etc. etc. Votre remarque ne concerne donc que les programmeurs professionnels.

                      Pour les constantes linux, il fait aller à la pêche dans la documentation linux, dans les fichiers include, dans les exemples de programmation assembleur que l'on trouve sur Internet.

                      Voici par exemple le contenu de mon fichier des constantes pour l'assembleur 32 bits constitué au fil des mois  :

                      /*constantes Linux syscall */
                      .equ EXIT,   1
                      .equ FORK,   2
                      .equ READ,   3
                      .equ WRITE,  4
                      .equ OPEN,   5
                      .equ CLOSE,  6
                      .equ EXECVE, 0xB
                      .equ PIPE,   0x2A
                      .equ IOCTL,  0x36

                      /* console */
                      .equ STDIN,  0
                      .equ STDOUT, 1
                      .equ STDERR, 2  

                      /*  fichier */
                      .equ O_RDONLY, 0
                      .equ O_WRONLY, 0x0001    
                      .equ O_RDWR,   0x0002          @ open for reading and writing

                      .equ O_CREAT,  0x0200          @ create if nonexistant
                      .equ O_TRUNC,  0x0400          @ truncate to zero length
                      .equ O_EXCL,   0x0800          @ error if already exists
                      .equ O_SYNC,   04010000        @ valeur en octal à vérifier ????

                      .equ S_IRWXU,  0x00700   /* user (file owner) has read, write, and execute permission */

                      .equ  PROT_READ,    0x1     /* Page can be read.  */
                      .equ PROT_WRITE,    0x2     /* Page can be written.  */
                      .equ PROT_EXEC,    0x4     /* Page can be executed.  */
                      .equ PROT_NONE,    0x0     /* Page can not be accessed.  */

                      .equ MAP_SHARED,    0x01    /* Share changes.  */
                      .equ MAP_PRIVATE,    0x02    /* Changes are private.  */

                      .equ MAP_FIXED,    0x10    /* Interpret addr exactly.  */
                      .equ MAP_FILE,    0
                      .equ MAP_ANONYMOUS,    0x20    /* Don't use a file.  */
                      .equ MAP_ANON,    MAP_ANONYMOUS

                      .equ MAP_DENYWRITE,    0x0800  /* ETXTBSY */
                      .equ MAP_FOOBAR,    0x0800  /* ETXTBSY */

                      .equ MS_ASYNC,    1        /* sync memory asynchronously */
                      .equ MS_SYNC,        2        /* synchronous memory sync */
                      .equ MS_INVALIDATE,    4        /* invalidate the caches */


                      //.equ FBIOGET_FSCREENINFO, 0x4602
                      /* Constantes générales */
                      .equ false, 0
                      .equ true,  1

                      /* constantes X11 */
                      .equ KeyPressed,  2
                      .equ ButtonPress, 4  
                      .equ MotionNotify,    6
                      .equ EnterNotify, 7
                      .equ LeaveNotify,  8
                      .equ Expose,   12  
                      .equ ClientMessage,    33      
                      .equ KeyPressMask, 1
                      .equ ButtonPressMask, 4
                      .equ ButtonReleaseMask, 8
                      .equ ExposureMask, 1<<15
                      .equ StructureNotifyMask, 1<<17
                      .equ EnterWindowMask, 1<<4
                      .equ LeaveWindowMask, 1<<5
                      .equ ConfigureNotify, 22


                      .equ GCForeground,    1<<2
                      .equ GCBackground, 1<<3
                      .equ GCLine_width, 1<<4
                      .equ GCLine_style, 1<<5
                      .equ GCFont,    1<<14

                      .equ CWBackPixel,    1<<1
                      .equ CWBorderPixel,    1<<3
                      .equ CWEventMask,    1<<11
                      .equ CWX,            1<<0
                      .equ CWY,             (1<<1)
                      .equ CWWidth,         1<<2
                      .equ CWHeight,         1<<3
                      .equ CWBorderWidth, 1<<4
                      .equ CWSibling,     1<<5
                      .equ CWStackMode,         1<<6


                      .equ InputOutput,    1
                      .equ InputOnly,    2

                      .equ InputHint,    1 << 0
                      .equ StateHint,    1 << 1
                      .equ IconPixmapHint,    1<< 2
                      .equ IconWindowHint,    1 << 3
                      .equ IconPositionHint,    1<< 4
                      .equ IconMaskHint,    1<< 5
                      .equ WindowGroupHint,    1<< 6
                      .equ UrgencyHint,    1 << 8
                      .equ WithdrawnState,    0
                      .equ NormalState,    1    /* most applications start this way */
                      .equ IconicState,    3    /* application wants to start as an icon */

                      .equ USPosition,    1 << 0    /* user specified x, y */
                      .equ USSize,        1 << 1    /* user specified width, height */
                      .equ PPosition,    1 << 2    /* program specified position */
                      .equ PSize,        (1 << 3)    /* program specified size */
                      .equ PMinSize,    (1 << 4)    /* program specified minimum size */
                      .equ PMaxSize,    (1 << 5)    /* program specified maximum size */
                      .equ PResizeInc,    (1 << 6)    /* program specified resize increments */
                      .equ PAspect,        (1 << 7)    /* program specified min and max aspect ratios */
                      .equ PBaseSize,    (1 << 8)
                      .equ PWinGravity,    (1 << 9)

                      .equ Button1MotionMask, 1<<8
                      .equ Button2MotionMask,  1<<9
                      .equ ButtonMotionMask,    (1<<13)

                      .equ CoordModeOrigin,    0
                      .equ CoordModePrevious,    1

                      .equ XYPixmap,    1
                      .equ ZPixmap,    2


                      .equ Complex,            0
                      .equ Nonconvex,            1
                      .equ Convex,            2

                      /*
                      #define KeyPress                2
                      #define KeyRelease              3
                      #define ButtonPress             4
                      #define ButtonRelease           5
                      #define MotionNotify            6
                      #define EnterNotify             7
                      #define LeaveNotify             8
                      #define FocusIn                 9
                      #define FocusOut                10
                      #define KeymapNotify            11
                      #define Expose                  12
                      #define GraphicsExpose          13
                      #define NoExpose                14
                      #define VisibilityNotify        15
                      #define CreateNotify            16
                      #define DestroyNotify           17
                      #define UnmapNotify             18
                      #define MapNotify               19
                      #define MapRequest              20
                      #define ReparentNotify          21
                      #define ConfigureNotify         22
                      #define ConfigureRequest        23
                      #define GravityNotify           24
                      #define ResizeRequest           25
                      #define CirculateNotify         26
                      #define CirculateRequest        27
                      #define PropertyNotify          28
                      #define SelectionClear          29
                      #define SelectionRequest        30
                      #define SelectionNotify         31
                      #define ColormapNotify          32
                      #define ClientMessage           33
                      #define MappingNotify           34
                      #define GenericEvent            35
                      */

                      • Partager sur Facebook
                      • Partager sur Twitter
                        29 novembre 2020 à 18:46:16

                        PaulDurelin a écrit:

                        Bonsoir.

                        Pour Michel Billaud : si si il y a des fous qui ne programment qu'en assembleur et donc qui font appel à des fonctions système pour afficher, lire écrire dans des fichiers, lancer des threads, utiliser le tas etc. etc. Votre remarque ne concerne donc que les programmeurs professionnels.

                        On trouve de tout quand on cherche, et chacun a bien le droit de s'amuser comme il veut, mais ça ne représente certainement pas un gros pourcentage, y compris parmi les non-professionnels (qui ont déjà fort à faire avec C ou autre).

                        Donc pas tellement d'amateurs pour faire ça. Dans tous les sens du terme, autant les non-professionnels que des gens qui aimeraient ça.

                        PS : si il faut aller chercher dans des fichiers pour trouver la valeur de constantes : faites un programme qui s'en occupe. en assembleur si vous voulez. Au moins il servira à quelque chose :-)

                        -
                        Edité par michelbillaud 29 novembre 2020 à 18:47:31

                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 décembre 2020 à 8:00:56

                          Bonjour à tous, mon problème est résolu puisque j'ai trouvé dans quel fichier trouver les informations qu'il me faut. Je n'ai pas les mêmes valeurs que vous car j'ai une architecture 64 bits, mais peu importe. Je programme en assembleur pour le plaisir. J'ai commencé avec le 8080 Intel, j'ai continué jusqu'au 80486, ça m'a beaucoup plu. Comme j'arrive à la retraite, j'ai le temps de m'y remettre. Quand on manipule des images bit par bit, je pense que l'assembleur est plus efficace que le C, mais surtout plus facile à programmer car on a tout ce qu'il faut pour travailler sur les bits. Par exemple, les instructions ror et rol ne me semblent pas avoir leur équivalent en C et ça complique de les construire. Merci et bonne journée. Très cordialement.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            2 décembre 2020 à 10:25:09

                            Vous savez, on est en 2020 si on lui demande poliment, le compilateur C sait reconnaitre et optimiser les bricolages habituels de ce genre.

                            Par exemple, si en C on écrit la fonction qui fait une rotation d'un bit vers la gauche

                            uint32_t rotate_left_1(uint32_t value) 
                            {
                               return (value << 1) | (value >> 31);
                            }
                            

                            on obtient le code suivant

                            rotate_left_1:
                            	movl	%edi, %eax
                            	roll	%eax
                            	ret
                            

                            et c'est pareil pour une rotation de 5

                            uint32_t rotate_left_5(uint32_t value) 
                            {
                               return (value << 5) | (value >> 27);
                            }
                            
                            /*
                            
                            rotate_left_5:
                            	movl	%edi, %eax
                            	roll	$5, %eax
                            	ret
                            */

                            On peut s'*imaginer* qu' écrivant du code en assembleur, ça optimise, mais ça reste grandement à prouver par des *mesures*. C'est pas parce qu'on s'est pris la tête à faire des trucs compliqués que c'est mieux.

                            En réalité, si on programme sérieusement sur des images et qu'on a besoin de performances, on s'est certainement écrit une bibliothèque de macros qui font les opérations de bas niveau dont on a souvent besoin.

                            Ensuite on regarde quelles sont les opérations critiques, celles qui bouffent réellement du temps (il faut *mesurer*, parce que l'intuition pifométrique ne marche pas du tout dans ce domaine). Si ça implique une des macros, on envisage de voir ce qu'on peut faire pour l'optimiser. Et on fait plusieurs versions qu'on compare, là aussi,  avec des *mesures*.

                            PS pareil pour la rotation sur N positions

                            uint32_t rotate_left(uint32_t value, unsigned offset) 
                            {
                            	return (value << offset) | (value >> (32-offset));
                            }
                            
                            /*
                            rotate_left:
                            	movl	%edi, %eax
                            	movl	%esi, %ecx
                            	roll	%cl, %eax
                            	ret
                            */
                            


                            Donc l'argument "le compilateur ne connait pas rol" ne tient pas.  C'est le langage C qui n'a pas d'opérateur de rotation, mais le compilateur sait reconnaitre le "pattern" d'une rotation et générer l'instruction qui va bien.



                            -
                            Edité par michelbillaud 2 décembre 2020 à 10:45:05

                            • Partager sur Facebook
                            • Partager sur Twitter
                              7 décembre 2020 à 22:02:21

                              Merci pour toutes ces informations. Je suis effectivement impressionné par le "savoir faire" du compilateur C ; je ne m'attendais pas du tout à ce que le code assembleur produit soit si bref. J'avais probablement une idée fausse sur la comparaison des performances de C et de l'assembleur. Je reconnais qu'il s'ajoute aussi l'argument de portabilité en faveur du C.

                              Merci beaucoup pour cette discussion très enrichissante.

                              Très cordialement.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                7 décembre 2020 à 22:07:36

                                Si on connait un peu l'assembleur, en regardant le code généré par le compilateur C (-O9), on apprend des techniques d'optimisation intéressantes.

                                (ceci dit, parfois, il se vautre un peu en se lançant dans une petite optimisation qui l'empêche d'en faire une plus intéressante. C'est un programme, pas un génie).

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  8 décembre 2020 à 13:43:53

                                  RolandThomas3 a écrit:

                                  Je programme en assembleur pour le plaisir. J'ai commencé avec le 8080 Intel, j'ai continué jusqu'au 80486, ça m'a beaucoup plu. Comme j'arrive à la retraite, j'ai le temps de m'y remettre. Quand on manipule des images bit par bit, je pense que l'assembleur est plus efficace que le C, mais surtout plus facile à programmer car on a tout ce qu'il faut pour travailler sur les bits. Par exemple, les instructions ror et rol ne me semblent pas avoir leur équivalent en C et ça complique de les construire. Merci et bonne journée. Très cordialement.


                                  Oui mais l'informatique à pas mal évolué , de plus les compilateurs prend les considérations d'optimisation d'intel et AMD (qui ont bien changer depuis le 8086 ou 80486).
                                  Par exemple la plupart des compilo n'utilise plus le vieux FPU du x87.
                                  Ils font tout via les instructions SSE.
                                  De plus le compilateur C va optimiser la mémoire cache (bien plus important que ror / rol , vu qu'un cache miss , c'est 100 cycles de pénalité).

                                  Bref sauf si on est un gros connaisseur de la micro-architecture et des optimisations modernes des processeurs, je doute que vous ferez mieux qu'un compilo C ;)

                                  Et c'est ce qui fait souvent défaut à ceux qui ont programmé en asm dans les années 80/90 , ils pensent encore que le CPU fonctionne pareil ^^'

                                  Par contre aimé le x86 outch , personnellement j'ai toujours trouvé le x86 horrible à programmé surtout si on a commencé avec du M68000 plus propre (et bien plus performant aussi à l'époque) :)


                                  -
                                  Edité par HelbaSama 8 décembre 2020 à 13:45:12

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    8 décembre 2020 à 15:50:03

                                    Le langage C est de bas niveau, et en connaissant un peu d'assembleur, on imagine facilement comment traduire "naïvement" une instruction C en instructions machine - ce que faisaient les premiers compilateurs -. Mais on n'en n'est plus là _du tout_.

                                    Prenons par exemple la bête copie d'un tableau

                                    void copier(int dst[], int src[], unsigned size)
                                    {
                                    	for (int i = 0; i < size; i++) {
                                    		dst[i] = src[i];
                                    	}
                                    }
                                    

                                    voila la version optimisée produite par le compilateur avec l'option -O9

                                    copier:
                                    .LFB0:
                                    	.cfi_startproc
                                    	testl	%edx, %edx
                                    	je	.L1
                                    	leaq	16(%rdi), %rcx
                                    	leal	-1(%rdx), %eax
                                    	cmpq	%rcx, %rsi
                                    	leaq	16(%rsi), %rcx
                                    	setnb	%r8b
                                    	cmpq	%rcx, %rdi
                                    	setnb	%cl
                                    	orb	%cl, %r8b
                                    	je	.L3
                                    	cmpl	$3, %eax
                                    	jbe	.L3
                                    	movl	%edx, %ecx
                                    	xorl	%eax, %eax
                                    	shrl	$2, %ecx
                                    	salq	$4, %rcx
                                    	.p2align 4,,10
                                    	.p2align 3
                                    .L4:
                                    	movdqu	(%rsi,%rax), %xmm0
                                    	movups	%xmm0, (%rdi,%rax)
                                    	addq	$16, %rax
                                    	cmpq	%rcx, %rax
                                    	jne	.L4
                                    	movl	%edx, %eax
                                    	andl	$-4, %eax
                                    	cmpl	%eax, %edx
                                    	je	.L1
                                    	movslq	%eax, %rcx
                                    	movl	(%rsi,%rcx,4), %r8d
                                    	movl	%r8d, (%rdi,%rcx,4)
                                    	leal	1(%rax), %ecx
                                    	cmpl	%ecx, %edx
                                    	jbe	.L1
                                    	movslq	%ecx, %rcx
                                    	addl	$2, %eax
                                    	movl	(%rsi,%rcx,4), %r8d
                                    	movl	%r8d, (%rdi,%rcx,4)
                                    	cmpl	%eax, %edx
                                    	jbe	.L1
                                    	cltq
                                    	movl	(%rsi,%rax,4), %edx
                                    	movl	%edx, (%rdi,%rax,4)
                                    	ret
                                    	.p2align 4,,10
                                    	.p2align 3
                                    .L3:
                                    	movl	%eax, %edx
                                    	xorl	%eax, %eax
                                    	jmp	.L6
                                    	.p2align 4,,10
                                    	.p2align 3
                                    .L8:
                                    	movq	%rcx, %rax
                                    .L6:
                                    	movl	(%rsi,%rax,4), %ecx
                                    	movl	%ecx, (%rdi,%rax,4)
                                    	leaq	1(%rax), %rcx
                                    	cmpq	%rdx, %rax
                                    	jne	.L8
                                    .L1:
                                    	ret
                                    

                                    IL y a eu un dépliage de boucle pour limiter les "bulles" dans le cache.

                                    Mais si on demande l'optimisation en taille du code (-Os)

                                    copier:
                                    .LFB0:
                                    	.cfi_startproc
                                    	xorl	%eax, %eax
                                    .L2:
                                    	cmpl	%eax, %edx
                                    	jbe	.L5
                                    	movl	(%rsi,%rax,4), %ecx
                                    	movl	%ecx, (%rdi,%rax,4)
                                    	incq	%rax
                                    	jmp	.L2
                                    .L5:
                                    	ret
                                    

                                    c'est pas pareil.

                                    ----

                                    Après, on peut se croire malin avec des pointeurs et un compteur descendant :

                                    void copier2(int *dst, int *src, unsigned size)
                                    {
                                    	while(size--) {
                                    		*dst++ = *src++;
                                    	}
                                    }
                                    

                                    perdu : il fait le même genre de pâté avec

                                    copier2:
                                    .LFB1:
                                    	.cfi_startproc
                                    	leal	-1(%rdx), %r8d
                                    	testl	%edx, %edx
                                    	je	.L20
                                    	leaq	16(%rsi), %rax
                                    	cmpq	%rax, %rdi
                                    	leaq	16(%rdi), %rax
                                    	setnb	%cl
                                    	cmpq	%rax, %rsi
                                    	setnb	%al
                                    	orb	%al, %cl
                                    	je	.L22
                                    	cmpl	$3, %r8d
                                    	jbe	.L22
                                    	movl	%edx, %ecx
                                    	xorl	%eax, %eax
                                    	shrl	$2, %ecx
                                    	salq	$4, %rcx
                                    	.p2align 4,,10
                                    	.p2align 3
                                    .L23:
                                    	movdqu	(%rsi,%rax), %xmm0
                                    	movups	%xmm0, (%rdi,%rax)
                                    	addq	$16, %rax
                                    	cmpq	%rcx, %rax
                                    	jne	.L23
                                    	movl	%edx, %ecx
                                    	andl	$-4, %ecx
                                    	movl	%ecx, %eax
                                    	subl	%ecx, %r8d
                                    	salq	$2, %rax
                                    	addq	%rax, %rdi
                                    	addq	%rax, %rsi
                                    	cmpl	%ecx, %edx
                                    	je	.L20
                                    	movl	(%rsi), %eax
                                    	movl	%eax, (%rdi)
                                    	testl	%r8d, %r8d
                                    	je	.L20
                                    	movl	4(%rsi), %eax
                                    	movl	%eax, 4(%rdi)
                                    	cmpl	$1, %r8d
                                    	je	.L20
                                    	movl	8(%rsi), %eax
                                    	movl	%eax, 8(%rdi)
                                    	ret
                                    	.p2align 4,,10
                                    	.p2align 3
                                    .L22:
                                    	xorl	%eax, %eax
                                    	jmp	.L25
                                    	.p2align 4,,10
                                    	.p2align 3
                                    .L27:
                                    	movq	%rdx, %rax
                                    .L25:
                                    	movl	(%rsi,%rax,4), %edx
                                    	movl	%edx, (%rdi,%rax,4)
                                    	leaq	1(%rax), %rdx
                                    	cmpq	%r8, %rax
                                    	jne	.L27
                                    .L20:
                                    	ret
                                    





                                    -
                                    Edité par michelbillaud 8 décembre 2020 à 15:55:59

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      8 décembre 2020 à 18:17:25


                                      Je suis très impressionné par les compilateurs actuel , ils sont capable de faire des optimisations assez poussé.
                                      (oui j'ai tenté pour ma part de battre le compilo C ,  si tu met les bonnes option et un code clair (pour l'aider à vectoriser ) , il se débrouille mieux que moi pour les instructions SSE/AVX >< )

                                      -
                                      Edité par HelbaSama 8 décembre 2020 à 19:32:23

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        8 décembre 2020 à 19:09:09

                                        Le genre de choses qu'on peut faire - sur l'exemple de copie d'un tableau, c'est d'utiliser une instruction de copie de 4 entiers à la fois (movdqu).

                                        Idée : on copie le début du tableau, tant qu'on peut le faire 4 par 4

                                        void copy(int dst[], int src[], int taille) 
                                        {
                                            int i;
                                            for(i = 0; i + 3 < taille; i += 4) {
                                                memcpy(dst+i, src+i, 4 * sizeof(int));
                                        
                                                /* 
                                                   dst[i]   = src[i];   dst[i+1] = src[i+1];
                                                   dst[i+2] = src[i+2]; dst[i+3] = src[i+3]; 
                                                */
                                            }
                                        
                                            for (  ; i < taille ; i++) {
                                                dst[i] = src[i];
                                            }
                                        }
                                        

                                        et on finit ce qui reste (0 à 3 éléments, donc 1 et demi en moyenne)  à la petite cuiller.


                                        Et là, ça optimise joyeusement

                                        copy2:
                                        .LFB1:
                                        	.cfi_startproc
                                        	cmpl	$3, %edx
                                        	jle	.L18
                                        	leal	-4(%rdx), %r8d
                                        	xorl	%eax, %eax
                                        	shrl	$2, %r8d
                                        	movl	%r8d, %ecx
                                        	addq	$1, %rcx
                                        	salq	$4, %rcx
                                        	.p2align 4,,10
                                        	.p2align 3
                                        .L16:
                                        	movdqu	(%rsi,%rax), %xmm0
                                        	movups	%xmm0, (%rdi,%rax)
                                        	addq	$16, %rax
                                        	cmpq	%rcx, %rax
                                        	jne	.L16
                                        	leal	4(,%r8,4), %eax
                                        .L15:
                                        	cmpl	%eax, %edx
                                        	jle	.L14
                                        	movslq	%eax, %rcx
                                        	movl	(%rsi,%rcx,4), %r8d
                                        	movl	%r8d, (%rdi,%rcx,4)
                                        	leal	1(%rax), %ecx
                                        	cmpl	%ecx, %edx
                                        	jle	.L14
                                        	movslq	%ecx, %rcx
                                        	movl	(%rsi,%rcx,4), %r8d
                                        	movl	%r8d, (%rdi,%rcx,4)
                                        	leal	2(%rax), %ecx
                                        	cmpl	%ecx, %edx
                                        	jle	.L14
                                        	movslq	%ecx, %rcx
                                        	addl	$3, %eax
                                        	movl	(%rsi,%rcx,4), %r8d
                                        	movl	%r8d, (%rdi,%rcx,4)
                                        	cmpl	%eax, %edx
                                        	jle	.L14
                                        	cltq
                                        	movl	(%rsi,%rax,4), %edx
                                        	movl	%edx, (%rdi,%rax,4)
                                        .L14:
                                        	ret
                                        

                                        (la boucle de 6 lignes à partir de L16)

                                        Comme on voit, la boucle de la fin a été dépliée, et c'est le code pour s'occuper des 1.5 derniers éléments qui  prend toute la place :-)

                                        -
                                        Edité par michelbillaud 8 décembre 2020 à 19:11:36

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          9 décembre 2020 à 16:27:47

                                          Bonjour.

                                          C'est quel type d'assembleur qui est produit par ce compilateur ?. En effet des instructions me semblent très bizarres comme leal    -4(%rdx), %r8d

                                          J'ai pas l'habitude de voir un -4 trainer devant une parenthèse !!

                                          De plus je suppose qu'il y a d'autres instructions auparavant car au début de ce listing, il fait un xor %eax,%eax qui va remettre à zéro les 32 bits de poids faibles du registre rax et un peu plus loin il utilise tout le registre rax. S'il reste quelque chose dans la partie haute bonjour les dégats !!

                                          Le compilateur doit donc savoir que seule la partie basse de rax a été utilisée.

                                          Mais je me demande aussi s'il y a vraiment un gain entre xor eax,eax et xor rax,rax  ?

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            9 décembre 2020 à 16:41:01

                                            C'est de la syntaxe AT&T donc sûrement du GCC (qui utilise cette syntaxe).

                                            "je me demande aussi s'il y a vraiment un gain entre xor eax,eax et xor rax,rax"
                                            ça c'est les constructeurs (Intel ou AMD) qui dise si tel ou tel instruction est plus rapidement traité  ,donc je suppose qu'ils ont du recommandé eax au lieu de rax.

                                            Mais là aussi c'est plus une recommandation , comme il est impossible de connaitre le taux de cycles des instructions sauf à la runtime  , tu peux ne pas avoir de différence comme en avoir.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              9 décembre 2020 à 16:41:23

                                              C'est produit par gcc. En gros il y a deux syntaxes Intel et att. Si C'est pas celle la, c'est l'autre.

                                              -
                                              Edité par michelbillaud 9 décembre 2020 à 16:42:52

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Constantes du noyau Linux

                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                              • Editeur
                                              • Markdown