【问题标题】:recursion in asm programasm程序中的递归
【发布时间】:2011-11-14 23:19:41
【问题描述】:

我有一个关于返回分段错误的 asm (x86 / GAS) 程序的问题。 关于斐波那契:我认为算法还可以:(伪代码)

fibo(int number){
    if (n < 2)
        return number;
    return fib(n - 1) + fib(n - 2);

我不明白为什么会出现错误。 一个 C 程序调用 asm 函数。

代码如下:

fibo:
    movl    4(%esp), %ebx    #argument n in %ebx
    cmpl    $2, %ebx          # test: is n < 2 ?
    jnl     recur            # no, recursion

    jmp     quit             # yes : quit

recur:


    movl    %ebx, %eax  # get value of argument n
    subl    $1, %eax     # n-1
    pushl   %eax        # push n-1
    call    fibo        # recursive call : fib(n-1)
    movl    %eax, %edx  # save result in  %edx
    movl    %ebx, %eax  # get value of argument n
    subl    $2, %eax     # n-2
    pushl   %eax        # push n-2
    call    fibo        # recursive call : fib(-2)
    addl    %edx, %eax  # add fib(n-1) + fib(n-2)

你能帮我找出段错误在哪里吗?

谢谢!

PS:这里是 ret :

quit:   movl    %ecx, %eax  #result in %ecx
        ret

【问题讨论】:

  • 等一下,您编写了这段代码,但您无法在调试器中单步执行它来定位问题?
  • 您似乎没有正确设置函数的堆栈框架——我没有看到 ebp 在任何地方被调整...
  • 见鬼,导致这种情况的输入是什么?这种特定的递归实现在堆栈上将非常困难。
  • 我是 asm 新手,我还没有使用调试器 @Oli Charlesworth
  • @lilawood:如果你要进行任何编程(尤其是汇编程序),你真的需要学习如何使用调试器。

标签: assembly recursion x86 fibonacci gnu-assembler


【解决方案1】:
  1. 如何从函数返回?
  2. 您是否希望您的 call 保留寄存器中的值?

答案将为您提供解决方案。

【讨论】:

    【解决方案2】:

    正如其他人指出的那样,您没有显示 ret 指令,这很重要。此外,您将 add 的中间结果保存在 edx 中。那是行不通的——接下来的递归调用也会这样做,并且会破坏你在这个调用级别上的值。您还需要将该中间值存储在堆栈中。

    【讨论】:

    • 我已经存储了中间值,但我不明白为什么我应该使用 %ebp 而我已经使用 %esp :复制堆栈?谢谢
    • 您不需要使用 ebp 设置显式堆栈帧。你可以像你一样使用 esp - 它在开发过程中更容易出错,仅此而已。
    猜你喜欢
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 2021-03-22
    相关资源
    最近更新 更多