4°C Nuageux
Nuageux
  • Technologies Web innovatrices.

Code


Convertir une chaîne de caractère ASCII en nombre décimal en assembleur
Publié par jcgauthier le 17 avril 2010 à 22 h 45
Mise à jour par jcgauthier le 1 mai 2010 à 9 h 54
Il faut parfois retourner à la base pour se rendre compte comment les langages de haut niveau nous rendent la vie facile. J'ai donc cru bon faire une série de procédures en assembleur pour processeurs x86 effectuant des tâches bien précises.

La première de cette série convertie une pile de caractères ASCII représentant des chiffres en un nombre décimal. Ceci est utile lorsque l'on doit lire un nombre entré par un utilisateur. L'exemple suivant prend en paramètre, par la pile, la liste des chiffres de gauche à droite, un pointeur vers un drapeau d'erreur, le nombre de caractères à lire et un drapeau de signe du nombre.

En boucle, un total cumulé est multiplié par 10 et ensuite additionné avec le prochain chiffre. À la fin, on fait un complément à deux sur le nombre si le drapeau de signer est 1.

Voici un exemple d'appel à la procédure :
   1: ; /// -------------------------------------------------------------------------
   2: ; /// Procédure main.
   3: ; /// Démarrage du programme.
   4: ; /// -------------------------------------------------------------------------
   5: title MASM main.asm
   6: .486
   7: .model flat, stdcall
   8: ExitProcess PROTO :DWORD
   9:  
  10: .data
  11: chiffres byte "123"             ; chiffres à convertir en nombre
  12: negatif dword 0                 ; drapeau pour nombre négatif
  13: erreur dword 0                  ; drapeau pour erreur
  14: espacePile dword 12             ; espace utilisé sur la pile
  15: nombre dword ?                  ; nombre converti
  16:  
  17: .code
  18: public _main
  19: extrn convertirNombre:proc
  20:  
  21: _main proc                      ; débute de la procédure main
  22: debut:
  23:     mov ecx, SIZEOF chiffres    ; obtenir le nombre de chiffres
  24:     lea esi, chiffres           ; obtenir l'adresse des chiffres
  25:     mov al, byte ptr[esi]       ; obtenir le premier caractère
  26:     cmp al, "-"                 ; vérifier si c'est un moins
  27:     jne prochain                ; sauter si ce n'est pas un moins
  28:     mov negatif, 1              ; c'est un négatif, assigner drapeau
  29:     inc esi                     ; avancer au prochain caractère
  30:     
  31: prochain:
  32:     movzx eax, byte ptr[esi]    ; obtenir le caractère
  33:     push eax                    ; empiler le caractère
  34:     inc esi                     ; pointer vers le prochain caractère
  35:     add espacePile, 4           ; 4 octets de plus seront utilisés
  36:     loop prochain               ; passer au prochain caractère
  37:  
  38:     lea eax, erreur             ; obtenir l'adresse pour le drapeau d'erreur
  39:     push eax                    ; empiler l'adresse
  40:     mov eax, SIZEOF chiffres    ; obtenir le nombre de chiffres
  41:     push eax                    ; empiler le nombre de chiffres
  42:     mov eax, negatif            ; obtenir la valeur du drapeau négatif
  43:     push eax                    ; empiler la valeur du drapeau
  44:     call convertirNombre        ; effectuer la conversion
  45:     add esp, espacePile         ; ajuster le pointeur de pile
  46:     mov nombre, eax             ; conserver le nombre converti
  47: terminer:
  48:     invoke ExitProcess, 0       ; terminer le programme
  49: _main endp                      ; fin de la procédure main
  50:  
  51: end _main                       ; fin du programme
Voici la procédure complète :
   1: ; /// -------------------------------------------------------------------------
   2: ; /// Convertie une pile de caractères ASCII en un nombre décimal.
   3: ; /// Le premier élément de la pile indique si le nombre est négatif,
   4: ; /// le deuxième élément est le nombre de caractères, le troisième
   5: ; /// est un pointeur (*) sur un drapeau pour retourner une erreur et
   6: ; /// chaque élément suivant est un caractère représantant un chiffre
   7: ; /// d'un nombre de droite à gauche.
   8: ; /// Exemple:   -123 =     |1|3|*|3|2|1|
   9: ; ///           12333 = |0|5|*|3|3|3|2|1|
  10: ; /// -------------------------------------------------------------------------
  11: title MASM Conversion ASII décimal (convertirNombre.asm)
  12: .486
  13: .model flat
  14:  
  15: .data
  16: multiplicateur dword 10            ; multiplicateur pour valeur décimale
  17: chiffre dword 0                    ; chiffre converti
  18: nombre dword 0                     ; nombre converti
  19: position dword 0                   ; position du chiffre
  20: iteration dword 0                  ; iteration lors de multiplication x10
  21: nombreNegatif dword 0              ; si le nombre est négatif
  22: erreurAdresse dword 0              ; pointeur sur le drapeau d'erreur
  23:  
  24: .code
  25: public _convertirNombre            ; rendre la procédure publique
  26: _convertirNombre proc
  27:     push ebp                       ; sauvagarder ebp sur la pile
  28:     mov ebp, esp                   ; mettre l'adresse du pointeur de pile dans ebp
  29:     push ebx                       ; sauvegarder ebx
  30:     push ecx                       ; sauvegarder ecx
  31:     push esi                       ; sauvegarder esi
  32:     mov esi, ebp                   ; pointer esi sur la pile
  33:     
  34:     add esi, 8                     ; obtenir l'adresse du drapeau négatif
  35:     mov ebx, [esi]                 ; si le nombre est négatif
  36:     mov nombreNegatif, ebx         ; assigner le drapeau nombre négatif
  37:     add esi, 4                     ; obtenir l'adresse du nombre de chiffre
  38:     mov ecx, [esi]                 ; nombre de chiffres du nombre
  39:     add esi, 4                     ; obtenir l'adresse du drapeau d'erreur
  40:     mov ebx, [esi]                 ; copier adresse
  41:     mov erreurAdresse, ebx         ; assigner l'adresse dans une variable
  42:     
  43:     mov eax, 4                     ; nombre d'octets par élément de pile
  44:     mul ecx                        ; multiplié par le nombre de chiffres sur la pile
  45:     add esi, eax                   ; avancer au bout de la pile de nombre
  46:     mov eax, 0                     ; initialiser le nombre a 0
  47: preVal:
  48:     cmp ecx, 10                    ; prévalidation pour les nombre > 10 caractères
  49:     ja erreurConv                  ; sauter s'il c'est le cas
  50:  
  51: prochainChiffre:
  52:     mul multiplicateur             ; multiplier par 10 (shl décimal 1 gauche)
  53:     jo erreurConv                  ; vérifier un dépassement dans le signe
  54:     jc erreurConv                  ; vérifier un dépassement dans la retenue
  55:     mov ebx, [esi]                 ; obtenir le caractère du chiffre
  56:     and ebx, 0Fh                   ; convertir en valeur numérique (-48)
  57:     add eax, ebx                   ; cumuler le nombre
  58:     jo erreurConv                  ; vérifier un dépassement dans le signe
  59:     jc erreurConv                  ; vérifier un dépassement dans la retenue
  60:     sub esi, 4                     ; obtenir l'adresse du prochain chiffre
  61:     loop prochainChiffre           ; passer au prochain chiffre
  62:  
  63:     cmp nombreNegatif, 0           ; si c'est un nombre négatif
  64:     je finConv                     ; si non, sauter à la fin
  65:     neg eax                        ; complément à deux
  66:     jmp finConv                    ; sauter à la fin
  67:  
  68: erreurConv:
  69:     mov eax, 0                     ; retourner le nombre 0
  70:     mov [erreurAdresse], 1         ; signaler une erreur de conversion
  71: finConv:
  72:     pop esi                        ; restaurer esi
  73:     pop ecx                        ; restaurer ecx
  74:     pop ebx                        ; restaurer ebx
  75:     pop ebp                        ; restaurer ebp
  76:     ret                            ; retourner à l'appelant
  77: _convertirNombre endp
  78: end
Étiquettes : Assembleur, Conversion
Problèmes de conversion d'un projet Web à une application Web (WebApplication)
Publié par jcgauthier le 18 novembre 2009 à 21 h 00
En faisant la conversion d'un projet Web vers une application Web, vous pouvez faire face à plusieurs problèmes. Le premier : comment démarrer la conversion. Je croyais qu'on pouvais faire la conversion à partir du projet de départ, mais non. Il faut créer l'application Web et y transférer tout le contenu du projet Web. Ensuite, à partir de l'application Web, vous pouvez choisir l'option « Convertir en application Web » sur le menu contextuel au niveau du projet. Ceci va convertir le tout.

Les problèmes commencent là. La plupart du temps, ce sera une référence qui manque, mais je suis tombé sur un cas où il y a fallu changer le code. Une petite ligne de code toute simple pour créer un ResourceManager ne fonctionnait plus. Soit les resources étaient déclarées deux fois dû à la différente manière de compiler, soient elles ne pouvaient plus être obtenues de la même façon.

Après avoir analysé la classe générée par une resource, je me suis rendu à l'évidence que la ligne suivante était fautive.
   1: private static ResourceManager dbResMgr = new ResourceManager(typeof(Resources.Database));
Elle doit être modifiée comme suit :
   1: private static ResourceManager dbResMgr =
   2:     new ResourceManager("Resources.Database", System.Reflection.Assembly.Load("App_GlobalResources"));
En espérant vous avoir sauvé quelques minutes de recherche :)
Étiquettes : WebApplication, Conversion
© 1999-2014 Grand Menhir. Tous droits réservés.