2016-02-23 2 views
7

Наконец, после долгого сеанса бесчисленных ошибок, надейтесь, что это окончательный вариант.Серия Фибоначчи в сборке x86

Нет ошибок компиляции или выполнения, просто логическая ошибка.

EDIT: (Fixed псевдокод)

Мой псевдокод:

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

for i from 1 to n{ 

    third=first+second 
    first=second 
    second=third 

} 
return third 

Это напечатает конечный результат серии.

My ассемблере:

Я добавил комментарии, где когда-либо возможные

.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 

код работает хорошо, но выход не удовлетворяет меня:

Выход: Loop Ran : 10 Times -----Final Number is : 11 ------

Прежде всего, я не знаю что конечное число находится в десятичной или шестнадцатеричной форме.

  • Предполагая, как десятичное: Серия Фибоначчи не имеет 11
  • Предполагая, как гекса: Серия Фибоначчи не имеет 17 (11 гекс = 17 декабря)

Что я делаю неправильно?

+0

Нет необходимости быть уверены в том, напечатанный номер в десятичная дробь. 'printf' использует строку' finalprint' как формат, и если это что-то вроде регулярного 'printf', он будет использовать'% d' для вывода как десятичного. – usr2564301

+2

Просто сравните свои комментарии с тем, что вы действительно хотели сделать;) 'NOW second = first' yeah, но вы хотели' first = second' ... oops. Вы получаете +1 для комментариев, вот как мы можем обнаружить вашу ошибку. – Jester

+0

Примечание: псевдокод возвращает правильное число Фибоначчи, хотя для n = 10 оно возвращает '144', технически * 12th * fib num (или' 89', в зависимости от того, как инициализируется 'n', но оно все еще слишком далеко). – usr2564301

ответ

4

Проблема заключалась в том, что мой фактический код не соответствовал моему псевдокоду, который привел к ошибке Logical.

Эта часть

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

Это дает first значение second, но мой псевдокод говорит "первый = второй", что означает дать значение second для first.

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

Final Рабочий код для x86 Процессор Intel:

Для дальнейших рефереров, я вывешивать рабочий код для архитектуры Intel x86

.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

Как общий комментарий, код, хранящий значения в регистрах, всегда проще, короче и быстрее, чем аналогичный код, который помещает значения в память, хотя нужно сделать немного больше работы, чтобы прокомментировать, какая переменная находится в регистре. Вы могли бы легко сделать это здесь. Еще один урок вы узнали о том, что обычно стоит на самом деле кодировать (а не псевдокод) алгоритм на языке более высокого уровня, прежде чем приступать к написанию кода сборки. Увидеть ошибку в HLL намного проще, чем увидеть ее в сборке. – Gene

+0

@Gene Извините, я полный новичок для Ассамблеи, поскольку он отличается. Я не понял, что ты сказал. Вы хотели сказать, что я должен также прокомментировать, какая переменная находится в регистре? а вместо '; переместить второй в ebx', я должен был написать' ebx = second'? Сначала я тестировал псевдокод в Javascript, и, похоже, я пропустил ошибку, так как мой код дает правильное число, но на два шага впереди запрошенного n-го числа, я сосредоточился на простоте, которая заставила меня пропустить эту небольшую ошибку. – Idkwhoami

+0

У вас все хорошо. Нет, я говорю, что вам не нужны места в памяти. Например. используйте esi, edi и edx для первого, второго и третьего. Это все еще оставляет 3 регистра для подсчета циклов, временных значений и т. Д. – Gene

Смежные вопросы