2016-07-16 32 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