Obligement - L'Amiga au maximum

Samedi 18 novembre 2017 - 05:45  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Assembleur - création d'une bibliothèque - 2e partie
(Article écrit par Frédéric Delacroix et extrait d'Amiga News - février 1995)


J'espère que vous avez bien digéré la théorie du mois dernier car, comme promis, je vous donne un exemple de bibliothèque, créée par la méthode décrite dans cet article. Bien qu'assez court et finalement pas d'une grande utilité, cet exemple a le mérite d'illustrer de façon concrète la marche à suivre.

La bibliothèque

Le rôle de cette bibliothèque, que j'ai baptisée "stringtools.library", est d'offrir des fonctions de base pour le traitement des chaînes de caractères. Il s'agit, pour la plupart, de clones de fonctions standards du C. Pour être honnête, je dois signaler que je me suis inspiré d'un article de Max paru dans Commodore Revue en décembre 1990.

J'ai également ajouté une routine de tri par bulles, tout ce qu'il y a de plus classique dans son principe. Petite particularité toutefois : au lieu d'utiliser une routine de comparaison fixe, cette routine, stBubbleSortHook(), fait appel à un hook (voir le fichier "utility/hooks.i"), ce qui lui permet de changer l'ordre de classement. On peut même faire du tri sur de tout autres objets que des chaînes de caractères. Il suffit de dire à la routine comment les comparer grâce à ce hook. Je vous renvoie au code source ci après pour plus de détails.

Le fichier "include" est également listé ici ; il est tout à fait standard, excepté que je l'ai fusionné avec le fichier définissant les LVO. On y définit la structure de base de la bibliothèque et d'autres choses utiles. La bibliothèque utilisant l'utility.library, est, pour son usage, réservée aux possesseurs de la version 37 (Kickstart 2.04) et plus (c'est-à-dire tout le monde, normalement).

Programme d'exemple

Afin d'illustrer le fonctionnement de stringtools.library, j'ai également ajouté un programme d'exemple. Son rôle est de trier les arguments qu'il reçoit sur sa ligne de commande, ainsi :

TestST Amiga News Amiga Injector Helloween donnera, dans l'ordre : Amiga, Amiga News, Helloween et Injector (attention, pour ce hook, les majuscules sont importantes).

Considérations de style

Première recommandation : ne faites pas de bibliothèque si ce n'est pas absolument indispensable. Premièrement, parce que c'est du travail supplémentaire pour le programmeur (vous !) qui doit faire attention à la réentrance (pas de variables globales sans sémaphores !), et deuxièmement parce que cela encombre, souvent inutilement, le tiroir Libs: de l'utilisateur (mon disque dur en comporte 129 !). Les bibliothèques sont réservées aux routines relativement délicates, répétitives ou encombrantes utilisées par plusieurs programmes. Les routines de la stringtools.library seront avantageusement inclues dans votre programme.

Si votre (grosse) application utilise quelques bibliothèques très spécifiques, placez celles-ci dans un répertoire spécial (les chemins complets sont des paramètres valides à OpenLibrary()). De cette façon, l'utilisateur s'y perdra moins...

Maintenez toujours une compatibilité descendante totale. Si vous ajoutez des fonctions à votre bibliothèque, vous devez incrémenter le numéro de version (pas seulement de révision) de façon à ce qu'une application puisse être sûre que ces nouvelles fonctions existent en fournissant le nouveau numéro de version à l'ouverture.

Si vous diffusez une bibliothèque dans le domaine public, assurez-vous que vous fournissez bien les fichiers includes C et assembleur, les autodocs (au format standard, pour qu'ils puissent être convertis par AD2AG), le fichier FD, des scripts d'installation, des exemples, des informations de révision. Comme référence, je ne manquerai pas de vous citer la remarquable reqtools.library de Nico François...

A la prochaine !

Si vous souhaitez que j'aborde un sujet précis ou des éclaircissements, n'hésitez pas à écrire à la rédaction, qui se fera un plaisir de transmettre vos requêtes...

Code source stringtools.i

; libraries/stringtools.i
; Fichier include pour stringtools.library
; ©F.Delacroix pour Amiga News
; version 1.0

IFND LIBRARIES_STRINGTOOLS_I
LIBRARIES_STRINGTOOLS_I    SET 1
 
ST_VERNUM   EQU 1
ST_REVNUM   EQU 0

   IFND     EXEC_TYPES_I
   include  exec/types.i
   ENDC

   IFND     EXEC_LIBRARIES_I
   include  exec/libraries.i
   ENDC 

   STRUCTURE StringToolsBase,LIB_SIZE
   ULONG     stb_SegList
   APTR      stb_ExecBase
   APTR      stb_UtilityBase
   LABEL     stb_SIZEOF

STRINGTOOLSNAME MACRO
    dc.b      'stringtools.library',0
    ENDM

; offsets pour les fonctions
 _LVOstStrLen         EQU -30
 _LVOstStrCmp         EQU -36
 _LVOstStrCpy         EQU -42
 _LVOstStrnCpy        EQU -48
 _LVOstStrCat         EQU -54
 _LVOstStrnCat        EQU -60
 _LVOstStrToUpper     EQU -66
 _LVOstStrToLower     EQU -72
 _LVOstBubbleSort     EQU -78
 _LVOstBubbleSortHook EQU -84
    ENDC 

Code source Library.s

opt  AMIGA
     OUTPUT   LIBS:stringtools.library
     include  exec/initializers.i
     include  exec/resident.i
     include  exec/alerts.i
     include  exec/execbase.i
     include  exec/exec_lib.i
     include  utility/utility_lib.i

     include  stringtools.i

; au cas où un clown essaierait d'exécuter la bibliothèque
ST moveq #-1,d0
   rts 

RomTag
    dc.w  RTC_MATCHWORD ; voir le mois dernier
    dc.l  RomTag,EndLib
    dc.b  RTF_AUTOINIT,ST_VERNUM
    dc.b  NT_LIBRARY,0
    dc.l  StringTools.Name,Library.ID
    dc.l  Library.Init

Library.Init
    dc.l  stb_SIZEOF
    dc.l  Functions.Table
    dc.l  Data.Table
    dc.l  Lib.InitRoutine
 
Functions.Table
    dc.l  Lib.Open
    dc.l  Lib.Close
    dc.l  Lib.Expunge
    dc.l  NullFunc
    dc.l  stStrLen
    dc.l  stStrCmp
    dc.l  stStrCpy
    dc.l  stStrnCpy
    dc.l  stStrCat
    dc.l  stStrnCat
    dc.l  stStrToUpper
    dc.l  stStrToLower
    dc.l  stBubbleSort
    dc.l  stBubbleSortHook
    dc.l  -1

Data.Table
    INITBYTE   LN_TYPE,NT_LIBRARY
    INITLONG   LN_NAME,StringTools.Name
    INITLONG   LIB_IDSTRING,Library.ID
    INITBYTE   LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
    INITWORD   LIB_VERSION,ST_VERNUM
    INITWORD   LIB_REVISION,ST_REVNUM
    dc.l       0 

Lib.InitRoutine ; (D0)Success=Lib.InitRoutine(Base,SegList)(D0,A0)
    movem.l    d7/a5-a6,-(sp)
    move.l     d0,a5
    move.l     a6,stb_ExecBase(a5)
    move.l     a0,stb_SegList(a5)
    lea        Utility.Name(pc),a1
    moveq      #37,d0
    jsr        _LVOOpenLibrary(a6)
    move.l     d0,stb_UtilityBase(a5)
    bne.s     .UtilOpened 
    move.l    #AG_OpenLib!AO_UtilityLib,d7
    jsr       _LVOAlert(a6)
    bra.s     .NoUtil
.UtilOpened
    move.l    a5,d0
.Back
    movem.l   (sp)+,d7/a5-a6
    rts
.NoUtil
    move.l    a5,a1
    moveq     #0,d0
    move.w    LIB_NEGSIZE(a5),d0
    sub.l     d0,a1
    add.w     LIB_POSSIZE(a5),d0
    jsr       _LVOFreeMem(a6)
    moveq     #0,d0
    bra.s     .Back

Lib.Open
    addq.w    #1,LIB_OPENCNT(a6)
    bclr      #LIBB_DELEXP,LIB_FLAGS(a6)
    move.l    a6,d0
    rts

Lib.Close
    subq.w    #1,LIB_OPENCNT(a6)
    bne.s     NullFunc
    btst      #LIBB_DELEXP,LIB_FLAGS(a6)
    bne.s     Lib.Expunge
NullFunc
    moveq     #0,d0
    rts

Lib.Expunge
       movem.l   d2/a5-a6,-(sp)
       move.l    a6,a5
       tst.w     LIB_OPENCNT(a5)
       beq.s     .DoIt
       bset      #LIBB_DELEXP,LIB_FLAGS(a5)
       moveq     #0,d0
       bra.s     .Ret
.DoIt  move.l    stb_ExecBase(a5),a6
       move.l    a5,a1
       jsr       _LVORemove(a6)
       move.l    stb_UtilityBase(a5),a1
       jsr       _LVOCloseLibrary(a6)
       move.l    stb_SegList(a5),d2
       moveq     #0,d0
       move.l    a5,a1
       move.w    LIB_NEGSIZE(a5),d0
       sub.l     d0,a1
       add.w     LIB_POSSIZE(a5),d0
       jsr       _LVOFreeMem(a6)
       move.l    d2,d0
.Ret   movem.l   (sp)+,d2/a5-a6
       rts 

; (D0)Length=stStrLen(String)(A0)
; retourne la longueur de la chaîne
stStrLen
       move.l    a0,-(sp)
       move.l    a0,d0
.Loop  tst.b     (a0)+
       bne.s     .Loop 
       sub.l     d0,a0
       move.l    a0,d0
       subq.l    #1,d0
       move.l    (sp)+,a0
       rts

; (D0,Z,N)Result=stStrCmp(String1,String2)(A0,A1)
; Compare les deux chaînes :
; D0<0 => String1 < String2
; D0=0 => String1 = String2
; D0>0 => String2 > String2
stStrCmp
       movem.l   d1-d2/a0-a1,-(sp)
       moveq     #0,d0 
.Loop  move.b    (a0)+,d1
       beq.s     .EOS1
       move.b    (a1)+,d2
       beq.s     .Sup
       cmp.b     d2,d1
       beq.s     .Loop
       bcs.s     .Inf
.Sup   moveq     #1,d0
       bra.s     .Ret
.EOS1  tst.b     (a1)+
       beq.s     .Ret
.Inf   moveq     #-1,d0
.Ret   movem.l   (sp)+,d1-d2/a0-a1
       rts

; stStrCpy(Buffer,String)(A0,A1)
; Copie la chaîne dans le tampon. Attention, le débordement
; du tampon n'est pas testé !
stStrCpy
       movem.l   a0-a1,-(sp)
.Loop  move.b    (a1)+,(a0)+
       bne.s     .Loop
       movem.l   (sp)+,a0-a1
       rts

; stStrnCpy(Buffer,String,Max)(A0,A1,D0)
; Pareil, mais ne copie au maximum que Max caractères.
stStrnCpy
       movem.l   a0-a1/d0,-(sp)
       subq.l    #1,d0
.Loop  move.b    (a1)+,(a0)+
       dbne      d0,.Loop
.Ret   movem.l   (sp)+,a0-a1/d0
       rts
 
; stStrCat(String1,String2)(A0,A1)
; String1 <- String1 + String2
; attention : pas de test de débordement de tampon !
stStrCat
       movem.l   a0-a1,-(sp)
.LLoop tst.b     (a0)+
       bne.s     .LLoop
       subq.l    #1,a0
.CLoop move.b    (a1)+,(a0)+
       bne.s     .CLoop
       movem.l   (sp)+,a0-a1
       rts

; stStrnCat(String1,String2,Max)(A0,A1,D0)
; pareil, mais au plus Max caractères de String2 seront ajoutés
; à String1.
stStrnCat
        movem.l   a0-a1/d0,-(sp)
.LLoop  tst.b     (a0)+
        bne.s     .LLoop
        subq.l    #1,a0
        subq.l    #1,d0
.CLoop  move.b    (a1)+,(a0)+
        dbne      d0,.CLoop
        movem.l   (sp)+,a0-a1/d0
        rts 

; stToUpper(String)(A0)
; convertit la chaîne en majuscules
stStrToUpper
        movem.l   d0-d1/a0-a2/a6,-(sp)
        move.l    a0,a2
        move.l    stb_UtilityBase(a6),a6
.Loop   move.b    (a2)+,d0
        beq.s     .End
        jsr       _LVOToUpper(a6)
        move.b    d0,-1(a2)
        bra.s     .Loop
.End    movem.l   (sp)+,d0-d1/a0-a2/a6
        rts

; stToLower(String)(A0)
; convertit la chaîne en minuscules
stStrToLower
        movem.l   d0-d1/a0-a2/a6,-(sp)
        move.l    a0,a2
        move.l    stb_UtilityBase(a6),a6
.Loop   move.b    (a2)+,d0
        beq.s     .End
        jsr       _LVOToLower(a6)
        move.b    d0,-1(a2)
        bra.s     .Loop
.End    movem.l   (sp)+,d0-d1/a0-a2/a6
        rts

; stBubbleSort(Array)(A0)
; Cas particulier de stBubbleSortHook() avec un hook
; consistant en un appel à stStrCmp() (tri alphabétique
; normal, en différenciant majuscules et minuscules) :
stBubbleSort
        lea       StrCmp.Hook(pc),a1

; stBubbleSortHook(Array,CompHook)(A0,A1)
; La fonction la plus délicate : trier un tableau de pointeurs sur des
; chaînes de caractères. Pour la comparaison, on utilise un hook
; fourni par l'utilisateur, ce qui permet différents types de tri.
; Le hook est appelé avec en A1 et A2 les deux chaînes à comparer.
stBubbleSortHook
        movem.l   d0-d3/a0-a6,-(sp)
        moveq     #0,d2
        move.l    a0,a5
        move.l    a1,d3
        move.l    stb_UtilityBase(a6),a6
.Loop1  tst.l     d2
        bne.s     .End
        moveq     #-1,d2 ; fini
        move.l    a5,a3
        tst.l     (a3)   ; a3= 1ere chaine **
        beq.s     .Loop1
.Loop2  lea       4(a3),a4   ; a4= 2nde chaine **
        tst.l     (a4)
        beq.s     .Loop1
        move.l    (a3),a1
        move.l    (a4),a2
        move.l    d3,a0
        jsr       _LVOCallHookPkt(a6)
        tst.l     d0
        ble.s     .NoSwap
        move.l    (a3),d0
        move.l    (a4),(a3)
        move.l    d0,(a4)
        moveq     #0,d2
        bra.s     .Loop2
.NoSwap move.l    a4,a3
        bra.s     .Loop2
.End    movem.l   (sp)+,d0-d3/a0-a6
        rts

stStrCmp.HookFunc
        move.l    a1,a0
        move.l    a2,a1
        bra       stStrCmp 

StrCmp.Hook      dc.l 0,0,stStrCmp.HookFunc,0,0

StringTools.Name dc.b 'stringtools.library',0
Library.ID       dc.b 'stringtools.library 1.0 (25.12.94)',0
Utility.Name     dc.b 'utility.library',0 
EndLib 

Code source "TestST.s"

opt AMIGA
          include   exec/exec_lib.i
          include   exec/exec.i
          include   dos/dos_lib.i
          include   stringtools.i

          move.l    4.w,a6
          lea       StringTools.Name(pc),a1
          moveq     #1,d0
          jsr       _LVOOpenLibrary(a6)
          move.l    d0,StringTools.Base
          beq.s     Exit
          lea       DOS.Name(pc),a1
          moveq     #37,d0
          jsr       _LVOOpenLibrary(a6)
          move.l    d0,DOS.Base
          beq.s     CloseST

          move.l    #Args.Template,d1
          move.l    #Args.Array,d2
          moveq     #0,d3
          move.l    DOS.Base(pc),a6
          jsr       _LVOReadArgs(a6)
          move.l    d0,Args.RDArgs
          beq.s     CloseDOS
          move.l    Args.Array(pc),a0
          move.l    StringTools.Base(pc),a6
          jsr       _LVOstBubbleSort(a6)
          move.l    Args.Array(pc),a2
          move.l    DOS.Base(pc),a6
PrintLoop
          move.l    (a2)+,d1
          beq.s     EndPrint
          jsr       _LVOPutStr(a6)
          move.l    #LineFeed,d1
          jsr       _LVOPutStr(a6)
          bra.s     PrintLoop 
EndPrint
          move.l    Args.RDArgs(pc),d1
          jsr       _LVOFreeArgs(a6) 
CloseDOS
          move.l    DOS.Base(pc),a1
          move.l    4.w,a6
          jsr       _LVOCloseLibrary(a6)
CloseST   move.l    StringTools.Base(pc),a1
          jsr       _LVOCloseLibrary(a6)
Exit      moveq     #0,d0
          rts 

StringTools.Base dc.l 0
DOS.Base         dc.l 0
Args.Array       dc.l 0 
Args.RDArgs      dc.l 0 

StringTools.Name STRINGTOOLSNAME
DOS.Name         DOSNAME
Args.Template    dc.b   'WORDS/M/A',0
LineFeed         dc.b   10,0


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]