2012-09-21 5 views
3

Je suis en train d'imprimer les numéros simplement dans la séquence soitConversion hexadécimaux/nombres décimaux (assemly-TASM)

1,2,3,4,5,6,7,8,9,10,11 En utilisant Loop, D'abord, j'ai converti chaque nombre en Hexa imprimé, le réinitialise à l'incrément décimal de 1, puis j'imprime le suivant jusqu'à ce que le nombre est égal à 9, Lorsque le nombre est égal à 9, j'ai utilisé DAA simplement le nombre et après avoir fait tourner et déplacer le nombre j'ai finalement stocké le résultat dans la chaîne.

La sortie est très bien jusqu'à ce que le 16, mais après 16 la séquence ne se répète,

sortie désiré:

1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16,17,18,19,20

courant de sortie 1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15,16,11,12,13,14,15

Pourquoi cela arrive-t-il ???

Voici mon code,

MOV CX,20 ;Number of Iterations 


MOV DX,1 



L1: 
    PUSH DX 
    ADD DX,30H 
    MOV AH,02H  ;PRINT Content of DX 
    INT 21H 
    POP DX 
    ADD DX,1 
    CMP DX,09d  ;If number is Greater than 9 jump to L2 
    JA L2 
LOOP L1 


    L2: 
     PUSH DX 
     MOV AX,DX 
     DAA   ;Convert to the Decimal 
     XOR AH,AH   ;SET AH to 0000 


     ROR AX,1  
     ROR AX,1  
     ROR AX,1  
     ROR AX,1  

     SHR AH,1 
     SHR AH,1 
     SHR AH,1 
     SHR AH,1 

     ADC AX,3030h 
     MOV BX,OFFSET Result 
     MOV byte ptr[BX],5   ; Length of the String 
     MOV byte ptr[BX+4],'$'  ;5th position of string , $=Terminator 
     MOV byte ptr[BX+3],AH  ;2nd Number onto 4th position 
     MOV byte ptr[BX+2],AL  ;3rd number onto 3rd Position 

     MOV DX,BX 
     ADD DX,02  ;1st 2 positions of String are type of string and  
            length respectively 
     MOV AH,09H ;to print the string 
     INT 21H   

     POP DX  
     ADD DX,1 

    LOOP L2 

MOV AH,4CH ;Return control to the DOS 
INT 21H 

P.S: J'ai pris l'aide de ce tableau pour comprendre les chiffres.

http://www.cheat-sheets.org/saved-copy/ascii.png

+1

vous devez compactify votre code, e. g. utiliser 'ror ax, 4' une fois au lieu de quatre fois' ror ax, 1'. De plus, tout le monde ne sait pas ce que font les appels d'interruption (je n'ai jamais assemblé sous DOS), il serait plus facile de savoir ce que fait le code si vous écrivez de courts commentaires dans ces lignes. - et s'il vous plaît supprimer autant de lignes vides que possible. Les lignes vides sont idéales pour la lisibilité, pour séparer les blocs logiques de code, mais plusieurs lignes vides conséquentes étirent trop la liste. – IdiotFromOutOfNowhere

+1

J'utilise DosBox en x64 pour je pense que c'est pourquoi je ne pouvais pas être en mesure d'utiliser directement ROR, 4 ou SHR, 4, je dois les utiliser séparément. et Commentaires ont été ajoutés – micheller

+1

IIRC, vous utilisez TASM, non? Peut-être une faille dans cet assembleur, puisque mes manuels Intel disent, que tourner/décaler par immédiat fonctionne également en mode 16 bits. Quoi qu'il en soit, qu'en est-il 'mov mot ptr [BX + 2], AX' - cela fonctionnerait-il? ;-) – IdiotFromOutOfNowhere

Répondre

3

juste lui donner un essai, bien que je ne suis pas sûr, et je ne peux pas tester rapidement cela.

Mais au lieu d'utiliser deux boucles, je recommande d'en utiliser une pour l'ensemble des nombres.

En outre, j'ai le sentiment que le problème est lié à l'instruction DAA, à laquelle je n'ai pas l'habitude, car elle n'est pas supportée en mode 64 bits.

Quoi qu'il en soit, voici ce que je ferais:

 mov cx,20 
     mov al,1 
     mov bl,10  ; divisor 
     mov bp,offset Result ; no need to load this in the loop!!! 

L1: mov dx,ax  ; save to register, not to stack 
     cmp ax,09d 
     ja L2   ; number has two digits 
     add al,30h  ; ASCII addend 

     ; insert your output code here 

     jmp L3   ; jump over the two digit code 
L2: xor ah,ah 
     div bl   ; divides AX by ten (no rotate or shift needed) 
         ; quotient in AL, remainder in AH (correct order for little endian) 
     add ax,3030h 

     ; insert your output code here (note that the buffer/string address is loaded to BP) 

L3: mov ax,dx 
     inc ax 
     loop L1 

     ; done 

Si vous ne me dérangerait pas si le nombre à un chiffre avaient un zéro, ce serait encore plus facile.

L'instruction div est probablement plus cher que daa, plus ror, plus shr, mais votre quad-rotation/changement sera encore pire: -/

(Comme je l'ai dit, je ne pouvais pas l'essayer ... laissant cette ouverture pour vous ... si cela ne fonctionne pas, il suffit de demander l'arrière)

[mise à jour:.

Une autre approche, en particulier pour épargner le div dans ce cas trivial de séparation de chiffres, serait d'ajouter 6 à des nombres plus grands neuf (i. e. 10d = 0ah - (+ 6) -> 16d = 10h; c'est ce que fait aussi daa), alors vous pouvez vous entendre avec la combinaison de rotation/décalage que vous avez utilisée auparavant.

Mieux encore étaient ajouter 246, puis à AX, après quoi vous pouvez simplement utiliser ror ax,8 (ou rol — n'a pas d'importance dans ce cas), i. e. 10d = 0ah - (+246) -> 256d = 100h, ainsi que 15d = 0fh - (+246) -> 261 = 105h. Tournez-le pour être 0001h ou 0501h respectivement, ajoutez 3030h, et vous avez terminé.

/mise à jour]

[mise à jour niveau = « 2 »

Qu'est-ce que le plaisir ... En fait, je l'intention de l'écrire dans la première mise à jour de niveau, mais a oublié en quelque sorte: au lieu de rol ling par 8 ou — si votre TASM ne supporte pas vraiment rol ling par huit immédiates — fois rouler par un, vous pouvez bien sûr faire également l'utilisation de l'instruction xchg, qui permute les valeurs entre les registres, dans ce cas

xchg al,ah 

ferait le travail de permuter le contenu de ces deux registres.

Il existe également une instruction bswap pour inverser l'ordre des octets dans un registre, mais elle n'est évidemment disponible que pour les registres de largeur supérieure à 32 bits.

/mise à jour]

+1

cela ne fonctionnerait pas pour le 20ème chiffre, ; 20d = 14h - (+ 6) -> 26d = 1Ah – micheller

+0

oui :) mais j'ai vraiment apprécié vos efforts et je l'ai simplifié de cette façon, pour chaque valeur de 0A à 19 nous devons ajouter 6d, de même pour les 10 prochaines valeurs, nous n'avons pas vraiment besoin d'ajouter 6d plutôt que nous devons ajouter 12d et pour les 10 prochaines valeurs, nous devons ajouter 18d et ainsi de suite :) ici vous aller :) \t \t \t; 10d = 0AH - (+ 6) -> = 16d 10h \t \t \t; 20d = 14h - (+ 12) -> = 32d 20h \t \t \t; 30d = 1Eh - (+ 18) -> 48h = 30h – micheller

3

Code 8086 seulement permis immédiat de 1 (ou cl) pour un nombre de décalages et tourne. Pour activer le code 286, dites à Tasm ".286" en haut de votre fichier. C'est une supposition.

La façon dont je me souviens que je l'habitude d'imprimer un nombre à deux chiffres dans al:

aam 
add ax, 3030h 
xchg al, ah 
int 29h 
mov al, ah 
int 29h 
0
.model small 
.stack 100 
.code 
     mov ax, 0ffffh   ; hex number to find it's bcd 
     mov  bx, 0000 
     mov  dh, 0 
l9 :  cmp  ax, 10000  ; if ax>10000 
     jb  l2 
     sub  ax, 10000  ; subtract 10000 
     inc  dh    ; add 1 to dh 
     jmp  l9 
l2 :  cmp  ax, 1000  ; if ax>1000 
     jb  l4 
     sub  ax, 1000 
     add  bx, 1000h  ; add 1000h to result 
     jmp  l2 
l4 :  cmp  ax, 100  ; if ax>100 
     jb  l6 
     sub  ax, 100 
     add  bx, 100h   ; add 100h to result 
     jmp  l4 
l6 :  cmp  ax, 10  ; if ax>10 
     jb  l8 
     sub  ax, 10 
     add  bx, 10h   ; add 10h to result 
     jmp  l6 
l8 :  add  bx, ax  ; add remainder 
           ; to result 
     mov  ah, 02    
     mov  cx, 0204h  ; Count to display 
           ; 2 digits 
     go:  rol dh, cl 
     mov  dl, dh 
     and  dl, 0fh 
     add  dl, 30h   ; display 2 msb digits  
     int  21h 
     dec  ch 
     jnz  go 
     mov  ch, 04h   ; Count of digits to be 
           ; displayed 
     mov  cl, 04h   ; Count to roll by 4 bits 
l12:  rol  bx, cl  ; roll bl so that msb 
           ; comes to lsb     
     mov  dl, bl   ; load dl with data to be 
           ; displayed 
     and  dl, 0fH   ; get only lsb 
     cmp  dl, 09   ; check if digit is 0-9 or letter A-F  
     jbe  l14 
     add  dl, 07   ; if letter add 37H else only add 30H 
l14:  add  dl, 30H 
     mov  ah, 02   ; Function 2 under INT 21H  (Display character) 
     int  21H 
     dec  ch    ; Decrement Count 
     jnz  l12 
     mov  ah, 4cH   ; Terminate Program 
     int  21H 
end 
+1

Bienvenue dans StackOverflow, vous voudrez peut-être lire [comment poster une bonne réponse] (http://stackoverflow.com/help/how-to-answer) avant de le faire.Donnez un peu de contexte expliquant pourquoi vous avez publié ce code et ce qu'il fait, pensez également à prendre le temps de formater votre réponse pour être facilement compris par les lecteurs. – Nacho