2016-07-16 78 views
-2

我已经写了一些代码(主要在c,程序集x86中的子程序)递归地计算所有二项系数并打印出n = 10的所有二项系数,受m < = n限制。装配x86/C递归二项式系数Segfault /打印帕斯卡三角形

所以基本上我试图输出n = 10的帕斯卡三角形。 (没有一个三角形的整个格式)

我的问题是,我得到了编译段错误,我无法弄清楚如何打印由递归函数生成的各个值。

Segmentation fault (core dumped) 

这里的主要程序:

#include <stdio.h> 

unsigned int result,m,n,i; 
unsigned int binom(int,int); 
int main(){ 

n=10; 


for (i=0; i<n+1;i++){ 
printf("i=%d | %d \n", i, binom(n,i)); 
} 

return; 


} 

和递归子程序:

.text 
    .globl binom 

binom: 
    mov  $0x00, %edx  #for difference calculation 
    cmp  %edi, %esi   #m=n? 
    je  equalorzero   #jump to equalorzero for returning of value 1 
    cmp  $0x00, %esi   #m=0? 
    je  equalorzero  
    cmp  $0x01, %esi   #m=1? 

    mov  %esi,%edx 
    sub  %edi, %edx 
    cmp  $0x01, %edx   # n-m = 1 ? 
    je  oneoronedifference 

    jmp  otherwise 

equalorzero: 
    add  $1, %eax   #return 1 
    ret 

oneoronedifference: 
    add  %edi, %eax   #return n 
    ret 

otherwise: 
    sub  $1, %edi   #binom(n-1,m) 
    call binom  
    sub  $1, %esi   #binom(n-1,m-1) 
    call binom 

这是GCC是给我

./runtimes 
i=0 | 12 
Segmentation fault (core dumped) 
+4

标签'否则:'后面有4行,但没有结束代码。是否缺少'ret'?在最后一次'调用binom'后,CPU将继续执行内存中的任意半随机数据,并且会发生段错误,挂起或一般不正确的操作。您应该在调试器中运行您的代码。 –

+0

我的理解是,当binom被调用时,它会递归到equalorzero或oneoronedifference,它们包含ret。 - 我会在那里添加一个ret来阻止它这样做。 –

+0

这并没有解决segfault - 也许它修复了另一个虽然,我敢肯定,我需要在最后的ret,以防止你提到 –

回答

1

两大问题与您的汇编代码是: 1)你不添加也不返回两个递归调用的总和; 2)您不会将您的本地人保存在堆栈中,以便通过递归调用消除它们 - 一旦您从调用中返回,就会使用错误的值。这里是我的代码的返工,一些变化OSX下是由于我的作文本:

递归子程序:

.text 
    .globl _binom 

_binom: 
    pushq %rbp     # allocate space on stack for locals 
    movq %rsp, %rbp 
    subq $24, %rsp 

    cmpl %edi, %esi   # m == n ? 
    je  equalorzero   # jump to equalorzero for returning of value 1 
    cmpl $0, %esi    # m == 0 ? 
    je  equalorzero  

    movl %esi, %edx 
    subl %edi, %edx 
    cmpl $1, %edx    # n - m == 1 ? 
    je  oneoronedifference 

    subl $1, %edi    # binom(n - 1, m) 
    movl %edi, -4(%rbp) 
    movl %esi, -8(%rbp) 
    callq _binom 

    movl %eax, -12(%rbp)  # save result to stack 

    movl -4(%rbp), %edi 
    movl -8(%rbp), %esi 
    subl $1, %esi    # binom(n - 1, m - 1) 
    callq _binom 

    addl -12(%rbp), %eax  # add results of the two recursive calls 
    addq $24, %rsp   # release locals space on stack 
    popq %rbp 
    retq 

equalorzero: 
    movl $1, %eax    # return 1 
    addq $24, %rsp   # release locals space on stack 
    popq %rbp 
    retq 

oneoronedifference: 
    movl %edi, %eax   # return n 
    addq $24, %rsp   # release locals space on stack 
    popq %rbp 
    retq 

主程序:

#include <stdio.h> 

extern unsigned int binom(int, int); 

int main() { 

    int n = 10; 

    for (int i = 0; i <= n; i++) { 
     printf("i=%d | %d\n", i, binom(n, i)); 
    } 

    return 0; 
} 

而且结果:

i=0 | 1 
i=1 | 10 
i=2 | 45 
i=3 | 120 
i=4 | 210 
i=5 | 252 
i=6 | 210 
i=7 | 120 
i=8 | 45 
i=9 | 10 
i=10 | 1