-20°C Dégagé
Dégagé
  • 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 :
; /// -------------------------------------------------------------------------
; /// Procédure main.
; /// Démarrage du programme.
; /// -------------------------------------------------------------------------
title MASM main.asm
.486
.model flat, stdcall
ExitProcess PROTO :DWORD

.data
chiffres byte "123"             ; chiffres à convertir en nombre
negatif dword 0                 ; drapeau pour nombre négatif
erreur dword 0                  ; drapeau pour erreur
espacePile dword 12             ; espace utilisé sur la pile
nombre dword ?                  ; nombre converti

.code
public _main
extrn convertirNombre:proc

_main proc                      ; débute de la procédure main
debut:
    mov ecx, SIZEOF chiffres    ; obtenir le nombre de chiffres
    lea esi, chiffres           ; obtenir l'adresse des chiffres
    mov al, byte ptr[esi]       ; obtenir le premier caractère
    cmp al, "-"                 ; vérifier si c'est un moins
    jne prochain                ; sauter si ce n'est pas un moins
    mov negatif, 1              ; c'est un négatif, assigner drapeau
    inc esi                     ; avancer au prochain caractère
    
prochain:
    movzx eax, byte ptr[esi]    ; obtenir le caractère
    push eax                    ; empiler le caractère
    inc esi                     ; pointer vers le prochain caractère
    add espacePile, 4           ; 4 octets de plus seront utilisés
    loop prochain               ; passer au prochain caractère

    lea eax, erreur             ; obtenir l'adresse pour le drapeau d'erreur
    push eax                    ; empiler l'adresse
    mov eax, SIZEOF chiffres    ; obtenir le nombre de chiffres
    push eax                    ; empiler le nombre de chiffres
    mov eax, negatif            ; obtenir la valeur du drapeau négatif
    push eax                    ; empiler la valeur du drapeau
    call convertirNombre        ; effectuer la conversion
    add esp, espacePile         ; ajuster le pointeur de pile
    mov nombre, eax             ; conserver le nombre converti
terminer:
    invoke ExitProcess, 0       ; terminer le programme
_main endp                      ; fin de la procédure main

end _main                       ; fin du programme
        
Voici la procédure complète :
; /// -------------------------------------------------------------------------
; /// Convertie une pile de caractères ASCII en un nombre décimal.
; /// Le premier élément de la pile indique si le nombre est négatif,
; /// le deuxième élément est le nombre de caractères, le troisième
; /// est un pointeur (*) sur un drapeau pour retourner une erreur et
; /// chaque élément suivant est un caractère représantant un chiffre
; /// d'un nombre de droite à gauche.
; /// Exemple:   -123 =     |1|3|*|3|2|1|
; ///           12333 = |0|5|*|3|3|3|2|1|
; /// -------------------------------------------------------------------------
title MASM Conversion ASII décimal (convertirNombre.asm)
.486
.model flat

.data
multiplicateur dword 10            ; multiplicateur pour valeur décimale
chiffre dword 0                    ; chiffre converti
nombre dword 0                     ; nombre converti
position dword 0                   ; position du chiffre
iteration dword 0                  ; iteration lors de multiplication x10
nombreNegatif dword 0              ; si le nombre est négatif
erreurAdresse dword 0              ; pointeur sur le drapeau d'erreur

.code
public _convertirNombre            ; rendre la procédure publique
_convertirNombre proc
    push ebp                       ; sauvagarder ebp sur la pile
    mov ebp, esp                   ; mettre l'adresse du pointeur de pile dans ebp
    push ebx                       ; sauvegarder ebx
    push ecx                       ; sauvegarder ecx
    push esi                       ; sauvegarder esi
    mov esi, ebp                   ; pointer esi sur la pile
    
    add esi, 8                     ; obtenir l'adresse du drapeau négatif
    mov ebx, [esi]                 ; si le nombre est négatif
    mov nombreNegatif, ebx         ; assigner le drapeau nombre négatif
    add esi, 4                     ; obtenir l'adresse du nombre de chiffre
    mov ecx, [esi]                 ; nombre de chiffres du nombre
    add esi, 4                     ; obtenir l'adresse du drapeau d'erreur
    mov ebx, [esi]                 ; copier adresse
    mov erreurAdresse, ebx         ; assigner l'adresse dans une variable
    
    mov eax, 4                     ; nombre d'octets par élément de pile
    mul ecx                        ; multiplié par le nombre de chiffres sur la pile
    add esi, eax                   ; avancer au bout de la pile de nombre
    mov eax, 0                     ; initialiser le nombre a 0
preVal:
    cmp ecx, 10                    ; prévalidation pour les nombre > 10 caractères
    ja erreurConv                  ; sauter s'il c'est le cas

prochainChiffre:
    mul multiplicateur             ; multiplier par 10 (shl décimal 1 gauche)
    jo erreurConv                  ; vérifier un dépassement dans le signe
    jc erreurConv                  ; vérifier un dépassement dans la retenue
    mov ebx, [esi]                 ; obtenir le caractère du chiffre
    and ebx, 0Fh                   ; convertir en valeur numérique (-48)
    add eax, ebx                   ; cumuler le nombre
    jo erreurConv                  ; vérifier un dépassement dans le signe
    jc erreurConv                  ; vérifier un dépassement dans la retenue
    sub esi, 4                     ; obtenir l'adresse du prochain chiffre
    loop prochainChiffre           ; passer au prochain chiffre

    cmp nombreNegatif, 0           ; si c'est un nombre négatif
    je finConv                     ; si non, sauter à la fin
    neg eax                        ; complément à deux
    jmp finConv                    ; sauter à la fin

erreurConv:
    mov eax, 0                     ; retourner le nombre 0
    mov [erreurAdresse], 1         ; signaler une erreur de conversion
finConv:
    pop esi                        ; restaurer esi
    pop ecx                        ; restaurer ecx
    pop ebx                        ; restaurer ebx
    pop ebp                        ; restaurer ebp
    ret                            ; retourner à l'appelant
_convertirNombre endp
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.
private static ResourceManager dbResMgr = new ResourceManager(typeof(Resources.Database));
Elle doit être modifiée comme suit :
private static ResourceManager dbResMgr =
    new ResourceManager("Resources.Database", System.Reflection.Assembly.Load("App_GlobalResources"));
En espérant vous avoir sauvé quelques minutes de recherche :)
Étiquettes : WebApplication, Conversion
© 1999-2016 Grand Menhir. Tous droits réservés.