组件x86/C-递归二项式系数SEGFULT/打印帕斯卡三角形

组件x86/C-递归二项式系数SEGFULT/打印帕斯卡三角形,c,recursion,assembly,segmentation-fault,x86-64,C,Recursion,Assembly,Segmentation Fault,X86 64,我已经编写了一些代码(c语言中的main,x86汇编语言中的子程序)来递归地计算所有的二项式系数,并打印出n=10的所有二项式系数,受m的限制汇编代码的两个主要问题是:1)您不能再加上或返回两个递归调用的和;2) 您没有将局部变量保存在堆栈上,因此它们会被递归调用清除——一旦从调用返回,您就使用了错误的值。以下是我对您的代码的修改,其中一些更改是由于我在OSX下编写了以下内容: 递归子程序: .text .globl binom binom: mov $0x

我已经编写了一些代码(c语言中的main,x86汇编语言中的子程序)来递归地计算所有的二项式系数,并打印出n=10的所有二项式系数,受m的限制汇编代码的两个主要问题是:1)您不能再加上或返回两个递归调用的和;2) 您没有将局部变量保存在堆栈上,因此它们会被递归调用清除——一旦从调用返回,您就使用了错误的值。以下是我对您的代码的修改,其中一些更改是由于我在OSX下编写了以下内容:

递归子程序:

    .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
    .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>

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;


}
#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;
}

在标签
之后,否则:
您有4行代码,但是没有任何内容可以结束代码。是否缺少
ret
?在最后一次调用binom后,CPU将继续执行内存中的任何半随机数据,并将出现故障、挂起或通常操作不正确。您应该在调试器中运行代码。我的理解是,当调用binom时,它将递归为equalorzero或oneoronedifference,其中包含ret。-我会在那里添加一个ret来阻止它这样做。这并没有修复SEGFULT-也许它修复了另一个错误,但我相信我最终需要这个ret来防止你提到的事情。你应该尝试gdb…@Egypt_Coder请花点时间阅读此评论。现在是学习如何使用调试器的时候了。在您的SO职业生涯中,您目前提出了8个问题,这些问题都与调试有关。如果你在第一次使用gdb之后就学会了使用gdb,那么你现在已经很熟练了。您的代码有很多初学者的错误(错误的寄存器用法、虚假的指令、缺少的条件),可以通过快速调试轻松修复,这在您的所有问题中都是不变的。我投票决定结束这个问题,我希望从现在起看到你们这一方的行为更加成熟。
    .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