2017-05-08 2 views
0

j'ai écrit un programme de l'Assemblée (x86_64 Linux MSNA) qui imprime un entier à la console, basé dans l'algorithme proposé mes commentaires dans ce post, qui est essentiellement ceci:lecture entrée utilisateur comme un entier

divide number x by 10, giving quotient q and remainder r 
emit r 
if q is not zero, set x = q and repeat 

Tout fonctionne très bien sous le script suivant:

section .bss 
     integer resb 100  ; it will hold the EOL 
     intAddress resb 8  ; the offset 

section .text 

     global _start: 

_start: 

     mov rax, 567 
     call _printProc 

     mov rax, 60 
     mov rdi, 0 
     syscall 


_printProc: ; here goes the algorithm described above. 

Après verbalisateurs, le nombre 567 est imprimé à l'écran (console).

Mais si j'essaie de faire la même chose mais en permettant à l'utilisateur d'entrer le nombre à imprimer en entier, je n'obtiens pas ce qui est attendu. Eh bien, pour ce faire, je fait les modifications suivantes (l'algorithme reste le même):

section .bss 
     integer resb 100  ; it will hold the EOL 
     intAddress resb 8  ; the offset 
     number resb 100 

section .text 

     global _start: 

_start: 

     ; getting user input 
     mov rax, 0 
     mov rdi, 0 
     mov rsi, number 
     mov rdx, 100 
     syscall 

     mov rax, [number]  ; passing the content at address number into rax 
     call _printProc 

     mov rax, 60 
     mov rdi, 0 
     syscall 


_printProc: ; here goes the algorithm described above. 

Mais dans ce cas, si je tape 567 je reçois 171390517. En fait, si je tape

0, I get 2608 
1, I get 2609 
2, I get 2610 

et ainsi de suite.

J'aimerais que certains d'entre vous aient une idée de ce qui est le problème dans le second cas et comment cela pourrait être corrigé.

+1

Pour l'entrée, vous devez convertir du texte en nombre (l'inverse de la conversion de sortie). Pour l'entrée '0' vous obtenez' 2608' car votre entrée est le code ascii de '0' qui est' 48' suivi d'un saut de ligne avec le code '10', et qui donne' 48 + 10 * 256 = 2608' petit endian. – Jester

+0

@Jester Donc dans ce cas je devrais soustraire 48 (code ASCII pour '0') du reste. Est-ce exact? Est-ce que je manque quelque chose d'autre? – Jazz

+1

Oui, et pour les chiffres multiples, vous devez bien sûr mettre à l'échelle la puissance appropriée de 10, et évidemment ignorer le saut de ligne. Vous ne le faites pas pendant la sortie, c'est une conversion d'entrée il n'y a pas de "reste". – Jester

Répondre

1

ce happends lorsque vous appelez cette

; getting user input 
    mov rax, 0 
    mov rdi, 0 
    mov rsi, number 
    mov rdx, 100 
    syscall 

est que votre entrée (par exemple « 1004 ») est écrit dans la mémoire à « numéro », caractère par caractère. Maintenant, vous avez le problème exact contraire vous l'intention de résoudre: « comment convertir une chaîne ASCII en valeur binaire »

l'algorithme de ce nouveau problème pourrait ressembler à ceci:

(assuming char_ptr points to the string) 
result = 0; 
while (*char_ptr is a digit) 
    result *= 10; 
    result += *char_ptr - '0' ; 
    char_ptr++;