【问题标题】:How to fix overflow for fibonacci sequence in nasm assembly?如何修复 nasm 汇编中斐波那契序列的溢出?
【发布时间】:2018-11-09 16:45:15
【问题描述】:

我是一名组装爱好者,我的任务之一是根据我的用户输入做一个斐波那契数列。因此,如果我的用户输入为 5,则输出将如下所示 0 1 1 2 3 它被放置在一个数组中,然后索引增加,并进行一些算术运算来实现序列。用户输入被限制为 25,所以如果用户输入是 25,我的输出应该像上面那样,一直到 46368 的值。起初,我用 al,bl 和 cl 来做算术的东西,但意识到 8 位寄存器太小,我改为 16 位。

在某些时候,数字显示为负数,我确实理解它是因为符号位,并且数字是有符号数 我如何使所有内容都未签名? 在某种程度上我已经尝试过 PRINT_UDEC 但在某个时间点这个数字会回到一个很小的数字并且不会继续加起来 实际上,当我在编写另一个程序时发生了同样的事情,并且我使用了 al,它是一个 8 位寄存器,所以我只是将其更改为 16 位寄存器,它就可以工作了 我也尝试将其更改为 32 位寄存器,但仍然无法正常工作! 据我所知(如果我错了,请纠正我) ax 的最大值可以达到 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

【问题讨论】:

  • 不要挑剔,但您的代码使用的是 32 位寄存器,而不是您所说的 16 位。 ;) 在输出变为负数之前,您在输出上看到的最高数字是多少?你需要展示你的输出。
  • 问题可能是 PRINT_DEC 或 PRINT_UDEC 打印出 16 位值,而不是 32 位值。查看是否有 32 位版本的 PRINT... 功能。对于无符号的 32 位寄存器,您应该能够达到 fib(47)。

标签: assembly nasm fibonacci


【解决方案1】:

尝试使用PRINT_DEC 4, [fibo + edx]PRINT_UDEC 4, [fibo + edx]
this source判断。


请注意,装配线不必以 ; 结尾 - 这是注释的开始。
此外,您的程序流程和编码风格也很混乱:除非您在打高尔夫球或利用某些技巧,否则不要跨函数共享 ret
向前比跳更难跟随 - 如果可能的话,更喜欢do {} while ();而不是while () {}
为标签指定有意义的名称,并在需要时采用使功能标签突出的命名约定。
你们是商品。

我发现如果汇编代码(一般代码)在空间上按逻辑块分组,则更容易遵循 - 避免文本墙效应。
你是zeroing registers 有两种不同的方式——这充其量是奇怪的(最坏的情况是可疑的)。

我认为您只需两条指令即可执行斐波那契步骤:

xchg eax, ebx
add ebx, eax

如果eaxf(n-1) 并且ebxf(n)

【讨论】:

    猜你喜欢
    • 2013-10-13
    • 2019-07-11
    • 2021-11-30
    • 2016-06-05
    • 2013-01-25
    • 2011-08-02
    • 2019-04-23
    • 1970-01-01
    相关资源
    最近更新 更多