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

x86 16-bits Assembleur Discussion :

Problème de routine


Sujet :

x86 16-bits Assembleur

  1. #1
    Futur Membre du Club
    Problème de routine
    Bonjour à tous. Pour m’entraîner, je me suis fait un petit code qui affiche un nombre. Ma fonction affiche le nombre (à l'aide des int du bios), mais j'ai l'impression que l’exécution de mon programme s'arrête après son appel... SI vous voyez où se trouve la quille, j'en serais très reconnaissant. Merci.
    Voici mon code :
    Code :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
     
    ;Fonction pour afficher un nombre entier sur 16 bits, stocké dans dx    
    putNb:
    	push ax
    	push bx
    	mov ax, dx
    	mov cx, 1
    	jmp .boucleNb
     
    	.boucleNb:
    		inc cx
    		;On divise ax par 10, en mettant 10 dans bh
    		mov bh, 10
    		div bh
    		mov dl, al
    		mov dh, 0
    		mov al, ah
    		mov ah, 0
    		add al, '0'
    		push ax
    		mov ax, dx
    		xor ax, 0
    		jz .boucle2Nb
    		jmp .boucleNb
     
    	.boucle2Nb:
    		pop ax
    		dec cx
    		xor cx, 0
    		jz .stopNb
    		mov ah, 0x0E
    		mov bx, 0x07
    		int 0x10
    		jmp .boucle2Nb
     
    	.stopNb:
    		pop bx
    		pop ax
    		ret

  2. #2
    Futur Membre du Club
    En fait, j'utilise cette fonction dans la boucle suivante. Peut être que c'est ici que mon programme plante (il parvient correctement jusqu'au ret). Sachant que maVariable est initialisée à 0.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    while1:
    	inc word [maVariable]
    	mov dx, [maVariable]
    	call putNb
    	mov cx,[maVariable]
    	xor cx, 9
    	jz while1

  3. #3
    Futur Membre du Club
    Je pense avoir trouvé l'origine du problème :
    J'utilise ce code pour faire un bootloader, mais au final, celui ci prend plus de 512 octets. Est ce que cela pourrais influencer le résultat ?

  4. #4
    Futur Membre du Club
    Bon, au final, même en changeant la taille occupée, ça ne change rien.

  5. #5
    Membre confirmé
    je dirait qu'il y as un problème dans le comptage des nombre de dépilement qui es fait dans cx, comme tu initialise cx a 1 tu auras toujours un dépilage de trop du coup tu auras dépilé une partie de l'adresse de retour et ça plante a iret

  6. #6
    Futur Membre du Club
    Ok c'était bien cela merci beaucoup !
    En fait je faisait le test de cx avant d'afficher la dernière partie de la variable, résultat ça m'avait induit en erreur. Sinon voilà le code corrigé :
    Code :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
     
    ;Fonction pour afficher un nombre entier sur 16 bits, stocké dans dx    
    putNb:
    	push ax
    	push bx
    	mov ax, dx
    	mov cx, 0
    	jmp .boucleNb
     
    	.boucleNb:
    		inc cx
    		;On divise ax par 10, en mettant 10 dans bh
    		mov bh, 10
    		div bh
    		mov dl, al
    		mov dh, 0
    		mov al, ah
    		mov ah, 0
    		add al, '0'
    		push ax
    		mov ax, dx
    		xor ax, 0
    		jz .boucle2Nb
    		jmp .boucleNb
     
    	.boucle2Nb:
    		pop ax
    		dec cx
    		mov ah, 0x0E
    		mov bx, 0x07
    		int 0x10
    		xor cx, 0
    		jz .stopNb
    		jmp .boucle2Nb
     
    	.stopNb:
    		pop bx
    		pop ax
    		ret


    Et encore merci pour ton aide

  7. #7
    Responsable Systèmes

    Petites remarques :

    la ligne 8 est inutile.
    ligne 23, si ton test déclenche le jmp ligne 24, le push de la ligne 20 n'est pas dépilé.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  8. #8
    Futur Membre du Club
    Ah oui, c'est vrai que la ligne 8 est inutile. Normalement, les push ligne 20 sont bien dépilés : Le compteur s'incrémente n fois, puis se décrémente n fois aussi, et étant donné que le pop se trouve au début de la boucle, ça marche correctement (dans tout les cas, si ce n'était pas correctement dépilé, le programme devrait s'arrêter non, vu que le ret dépile le haut de la pile, et que dans ce cas, le haut de la pile ne contiendrait pas l'adresse de l'instruction suivante, non ?). Par exemple, pour le nombre 25, on a l’exécution suivante :
    -appelle de putNb
    -On empile ax et bx
    -ax vaut 25
    -cx vaut 1
    -ax/10 -> ah = 5, al = 2
    -dx = 2
    -ax = '5'
    -on empile ax
    -ax = dx = 2, donc on boucle
    -cx vaut 2
    -ax/10 -> ah = 2, al = 0
    -dx = 2
    -ax = '2'
    -on empile ax
    -ax = dx = 0, donc on saute à la boucle suivante

    on dépile ax
    cx vaut 1
    on affiche ax (2)
    cx != 0, on boucle
    on dépile ax
    cx vaut 0
    on affiche ax (5)
    on retourne, en dépilant ax et bx.
    Donc on a bien deux empilements et deux dépilements. Cela fait la même chose quelque soit la longueur du nombre. Ensuite, peut-être que je n'ai pas compris ton message, c'est possible
    Et sinon, merci pour ta réponse, j'enlève la ligne 8 de ce pas

  9. #9
    Responsable Systèmes

    Au niveau de la ligne 23, si le jz ne déclenche pas un saut vers .boucle2Nb, alors ligne 24 tu auras un jmp vers .boucleNb ligne 10, qui effectuera un push ligne 20 qui éventuellement ressautera ligne 10 après le jz qui refera un push ligne 20.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  10. #10
    Futur Membre du Club
    Oui je sais, c'est le but. J'empile les caractères représentant, puis je les dépile pour les afficher dans le bon ordre. Car ensuite je dépile tout autant de fois que j'ai empilé.

  11. #11
    Responsable Systèmes

    J'ai pas testé le code, ou est le nombre de caractères à lire ? Mais si tu es sûr de ton coup .
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  12. #12
    Futur Membre du Club
    En l’occurrence je n'affiche pas une chaîne mais un nombre, convertit à l'aide de modulo et de divisions dans la première boucle, où j'incrémente cx à chaque fois et met le résultat du modulo dans la pile. Comme j'incrémente le compteur à chaque itération, je sais combien de fois j'ai empilé (et combien de caractères afficher). Ce que je fais dans la deuxième boucle en les dépilant.

###raw>template_hook.ano_emploi###