2016-02-23 16 views
7

Finalmente dopo una lunga sessione di innumerevoli errori, spero che questo sia l'ultimo.Fibonacci Series in Assembly x86

Nessun errore di compilazione o di runtime, solo un errore logico.

EDIT: (Pseudocodice fisso)

mio Pseudocodice:

first = 1; 
second = 1; 
third = 0; 

for i from 1 to n{ 

    third=first+second 
    first=second 
    second=third 

} 
return third 

Questo sarebbe stampare il risultato finale della serie.

My Code Montaggio:

Ho aggiunto commenti dove mai possibile

.386 
.model flat,stdcall 
option casemap:none 

.data 
timestell  db "Loop Ran : %d Times -----",0  ;format string 
fmtd db "%d",0 
finalprint db "Final Number is : %d ------",0  ;format string 
times dd 0Ah          ;times to loop 
first dd 1h 
second dd 1h 
third dd 0h 


.data? 

retvalue1 dd ?    ;we will initialize it later 

.code 
include windows.inc 
include user32.inc 
includelib user32.lib 
include kernel32.inc 
includelib kernel32.lib 
includelib MSVCRT 
extrn printf:near 
extrn exit:near 

public main 
main proc 


     mov ecx, times  ;loop "times" times 
     mov eax,0   ;just to store number of times loop ran 
     top:     ;body of loop 
     cmp ecx, 0   ;test at top of loop 
     je bottom   ;loop exit when while condition false 
     add eax,1   ;Just to test number of times loop ran 
     mov ebx,first  ;move first into ebx 
     add ebx,second  ;add ebx, [ first+second ] 
     mov third,ebx  ;Copy result i.e ebx [first+second] to third 
     xor ebx,ebx   ;clear for further use 
     mov ebx,first  ;move first into ebx 
     mov second,ebx  ;copy ebx to second [NOW second=first] 
     xor ebx,ebx   ;clear for later use 
     mov ebx,third  ;move thirs into ebx 
     mov second,ebx  ;copy ebx to third [NOW second=third] 
     xor ebx,ebx   ;clear it 
     dec ecx    ;decrement loop 
     jmp top    ;Loop again 

     bottom: 
      mov retvalue1,eax  ;store eax into a variable 
      push retvalue1   ;pass this variable to printf 
      push offset timestell ;pass Format string to printf  
      call printf    ;Print no. of times loop ran 
      push third    ;push value of third to printf 
      push offset finalprint ;push the format string 
      call printf    ;Print the final number 


     push 0  ;exit gracefully 
     call exit  ;exit system 

main endp 

end main 

Il codice funziona bene, ma l'uscita non mi soddisfa:

uscita: Loop Ran : 10 Times -----Final Number is : 11 ------

Prima di tutto non sono rea Sono sicuro che il numero finale è in forma decimale o esadecimale.

  • Assumendo come decimali: Fibonacci Series non ha 11
  • Assumendo come esadecimale: Fibonacci Series non ha 17 (11 hex = 17 dicembre)

Che cosa sto facendo sbagliato?

+0

Non c'è bisogno di essere sicuri se il numero stampato è in decimale. 'printf' usa la stringa' finalprint' come formato, e se assomiglia a un normale 'printf', userà'% d' come output decimale. – usr2564301

+2

Basta confrontare i tuoi commenti con quello che volevi davvero fare;) 'ORA secondo = prima' sì ma volevi' primo = secondo' ... oops. Ottieni un +1 per i commenti, è così che possiamo individuare il tuo errore. – Jester

+0

Nota: lo pseudocodice restituisce il numero corretto di Fibonacci, anche se per n = 10 restituisce '144', tecnicamente il * 12th * numero di fib (o' 89', a seconda di come 'n' viene inizializzato, ma è ancora troppo lontano). – usr2564301

risposta

4

Il problema era che il mio codice effettivo non corrispondeva al mio pseudocodice che ha provocato l'errore logico.

Questa parte

 mov ebx,first  ;move first into ebx 
    mov second,ebx  ;copy ebx to second [NOW second=first] 

Questo dà first valore second, ma il mio pseudocodice dice "prima = secondo", il che significa dare valore second-first.

 mov ebx,second  ;move second into ebx 
    mov first,ebx  ;copy ebx to second [NOW first=second] 

finale codice di lavoro per x86 Intel Processor:

Per ulteriori referenti, sto inviando un codice di lavoro per x86 Intel

.386 
.model flat,stdcall 
option casemap:none 

.data 
timestell db "Loop Ran : %d Times -----",0   ;format string 
finalprint db "%d th Fibonacci number is %d",0  ;format string 
times  dd 14h         ;times to loop 
first dd 1h 
second dd 1h 
third dd 0h 



.code 
include windows.inc 
include user32.inc 
includelib user32.lib 
include kernel32.inc 
includelib kernel32.lib 
includelib MSVCRT 
extrn printf:near 
extrn exit:near 

public main 
main proc 


     mov ecx, times  ;set loop counter to "times" time 
     sub ecx,2   ;loop times-2 times 

     top: 
     cmp ecx, 0   ; test at top of loop 
     je bottom   ; loop exit when while condition false 
     xor ebx,ebx   ;Clear ebx 
     mov ebx,first  ;move first into ebx 
     add ebx,second  ;add ebx, [ first+second ] 
     mov third,ebx  ;Copy result i.e ebx [first+second] to third 
     xor ebx,ebx   ;clear for further use 
     mov ebx,second  ;move second into ebx 
     mov first,ebx  ;copy ebx to second [NOW first=second] 
     xor ebx,ebx   ;clear for later use 
     mov ebx,third  ;move thirs into ebx 
     mov second,ebx  ;copy ebx to third [NOW second=third] 
     xor ebx,ebx   ;clear it 
     dec ecx    ;decrement loop 
     jmp top    ;Loop again 

     bottom: 
     push third 
       push times    ;push value of third to printf 
       push offset finalprint ;push the format string 
       call printf    ;Print the final number 
     push 0  ;exit gracefully 
     call exit  ;exit system 

    main endp 

end main 
+0

Come commento generale, il codice che memorizza i valori nei registri è sempre più semplice, più breve e più veloce di un codice simile che inserisce i valori nella memoria, anche se è necessario fare un po 'più di lavoro per commentare quale variabile è in quale registro. Potresti averlo fatto facilmente qui. Un'altra lezione che hai imparato è che di solito è utile codificare (non pseudocodificare) l'algoritmo in un linguaggio di livello superiore prima di impegnarsi nello scrivere il codice assembly. Vedere un errore in HLL è molto più semplice che vedere lo stesso in assembly. – Gene

+0

@Gene Spiacente, sono un novizio completo per Assembly in quanto differisce. Non ho capito cosa hai detto. Intendevi dire che dovrei anche commentare quale variabile è in quale registro? come invece di '; move second into ebx' dovrei aver scritto' ebx = second'? Ho provato lo pseudocode in Javascript per primo e mi sembra di aver mancato l'errore dato che il mio codice fornisce il numero corretto ma due passi avanti rispetto all'nno numero richiesto, mi sono concentrato sulla semplicità che mi ha fatto perdere questo piccolo errore. – Idkwhoami

+0

Stai andando bene. No, sto dicendo che non ti servivano affatto le locazioni di memoria. Per esempio. usa esi, edi ed edx per primo, secondo e terzo. Questo lascia ancora 3 registri per il conteggio dei cicli, i valori temporanei, ecc. – Gene