Как исправить переполнение для последовательности Фибоначчи в сборке носа? - PullRequest
0 голосов
/ 09 ноября 2018

Я - любитель в сборке, и одно из моих заданий - сделать последовательность Фибоначчи на основе моего пользовательского ввода. Так что, если мой пользовательский ввод 5, вывод будет выглядеть так 0 1 1 2 3 Он помещается в массив, а затем индекс увеличивается, и выполняется некоторая арифметическая операция для достижения последовательности. Пользовательский ввод ограничен 25, поэтому если пользовательский ввод должен быть 25, мой вывод должен выглядеть примерно так, как указано выше, вплоть до значения 46368. Сначала я использовал al, bl и cl для выполнения арифметических операций, но, понимая, что 8-битные регистры слишком малы, я изменил на 16-битные.

В какой-то момент число получается отрицательным, и я понимаю, что это похоже на бит знака, а число - число со знаком. как сделать все без знака? В некотором смысле я уже пытался сделать PRINT_UDEC, но в какой-то момент число возвращается к небольшому числу и не продолжает складывать и у меня фактически произошло то же самое, когда я делал кодирование другой программы, и я использовал al, который является 8-битным регистром, поэтому я просто изменил его на 16-битный регистр, и он работал Я попытался изменить его на 32-битные регистры тоже, но он все еще не работает! насколько я знаю (поправьте меня, если я ошибаюсь), наибольшее значение топора может быть до 65536? и 25-е число последовательности Фибоначчи - 46368, которое все еще находится в диапазоне 16-битного регистра. Как я могу исправить переполнение этого?

%include "io.inc"

section .bss
fibo    resb 26 * 4; reserve an array of 25 uninitialized bytes
userInput   resb 4 ; reserve 4 bytes for userInput

section .text
global _main
_main:
    mov ebp, esp ; entry point for correct debugging
    xor edx, edx ; initializing my secondary index to 0
    mov eax, 0 ; a = 0
    mov ebx, 1 ; b = 1
    mov ecx, 0 ; c = 0

    PRINT_STRING "Enter a number between 3 and 25 inclusively:" ;prompt user for integer input
    NEWLINE
    GET_DEC 4, userInput ; 

    mov edi, userInput ; 
    mov esi, fibo ; 
    call indexInc ; 
    mov edx, 0 ; 
    call printarray ; 

indexInc:
    mov [esi], eax ; moves the a = 0 in the first element of the array
    inc esi ; increases array index
    mov [esi], ebx ; moves the b = 1 in the second element of the array
    inc esi ; increases array index
    mov edx, 3 ; secondary pointer for comparison purposes

forloop:
    cmp edx, [userInput] ; 
    jg term ;
    add ecx, eax ; 
    add ecx, ebx ; 
    mov [esi], ecx ; 
    mov eax, ebx ; 
    mov ebx, ecx ; 
    xor ecx, ecx ; 
    inc esi ; increase array index
    inc edx ; increase secondary pointer
    jmp forloop ; 

printarray:
    cmp edx, [userInput] ; 
    je term ; 
    PRINT_DEC 1, [fibo + edx] ; 
    NEWLINE
    inc esi ; increase array index
    inc edx ; increase pointer
    jmp printarray ; 

term:
    ret ; terminate program

1 Ответ

0 голосов
/ 10 ноября 2018

Попробуйте использовать PRINT_DEC 4, [fibo + edx] или PRINT_UDEC 4, [fibo + edx].
Судя по этому источнику .


Обратите внимание, что сборочные линии не должны заканчиваться ; - это начало комментария.
Кроме того, поток ваших программ и стиль кодирования запутаны: не делитесь ret между функциями, если вы не играете в гольф или не используете какой-то трюк.
Прыжки вперед сложнее, чем прыжки назад - если возможно, предпочтительнее do {} while ();, чем while () {}.
Дайте меткам значимые имена и, если необходимо, примите соглашение об именовании, которое выделяет метки функций.
Ваши комментарии являются товаром.

Мне было проще следовать ассемблерному коду (коду в целом), если он пространственно сгруппирован в логический блок - избегая эффекта текстовой стены.
Вы обнуляете регистры двумя различными способами - это в лучшем случае странно (в худшем случае подозрительно).

Я думаю, что вы можете выполнить шаг Фибоначчи всего двумя инструкциями:

xchg eax, ebx
add ebx, eax

, если eax равно f(n-1) и ebx равно f(n)

...