递归Pascal三角形(组合函数)汇编

时间:2014-05-29 10:30:16

标签: assembly recursion x86-64 pascals-triangle yasm

我正在尝试在程序集中编写递归组合函数 Yasm (类似于nsam))。 我不能使用循环,乘法或除法。

我确定我在正确的轨道上但是在我进入第二个内部函数调用时遇到了问题。任何人都可以帮助我并告诉我哪里出错了吗?

编辑:这是我更新的代码,它会返回结果,但并不总是正确的。我想我必须有一点点逻辑错误。

    mov     rax, [n]
    push    rax
    mov     rax, [k]
    push    rax
    call    func    
    ...     ...     program continues from here

 func:                      
    push    rbp 
    mov     rbp, rsp

    push    rdi
    push    rsi

    cmp     rsi, 0
    je      stopcond
    cmp     rdi, rsi
    jne     contin

stopcond:
    mov     rax, 1
    jmp     endfunc
contin:
    ;C(n-1,k-1)
    mov     rax, [rsp]  ; This is k
    dec     rax
    mov     rdx, rax
    mov     rax, [rsp+8]  ; This is n
    dec     rax
    mov     rsi, rdx
    mov     rdi, rax
    call    func

    mov     rbx, rax
    mov     rax, [rsp+8]  ; This is n
    dec     rax
    mov     rdx, rax
    mov     rax, [rsp]  ; This is k
    mov     rsi, rax
    mov     rdi, rdx
    call    func

    add     rax, rbx

endfunc:
    add     rsp, 16
    pop     rbp
    ret

这是我一直用作参考的javascript实现

function(n,k) {
    if ( k==0 || k==n ) {
        return 1
    } else {
        return C(n-1,k-1) + C(n-1,k)
    }
}

1 个答案:

答案 0 :(得分:2)

  1. C(n-1,k)调用不正确,因为raxrbx都已经递减,递归调用无论如何都会破坏它们的值。简单的解决方法是从堆栈重新加载参数。
  2. 同样,递归调用将使用rdx作为自己的临时调用,从而覆盖调用者的副本。解决方案:您应该在堆栈上分配一个局部变量,并将其用作临时存储。
  3. 您没有恢复堆栈指针。在endfunc,您应该插入mov esp, ebp
  4. 你没有遵循通常的召唤惯例。如果您同意呼叫者,这不是问题,但可能仍然是一个好主意。您可以在wikipedia
  5. 快速了解详情

    PS:通常的建议适用:学会使用调试器,这样你就可以修复自己的错误。