2016-07-16 34 views
-2

Ich habe etwas Code (main in c, Unterprogramm in Assembly x86) geschrieben, um alle Binomialkoeffizienten rekursiv zu berechnen und alle Binomialkoeffizienten mit n = 10 auszudrucken , eingeschränkt durch m < = n.Assembly x86/C -Recursive Binomialkoeffizient Segfault/Printing Pascal Dreieck

Also im Grunde versuche ich ein pascals Dreieck für n = 10 auszugeben. (ohne das ganze Format eines Dreiecks)

Mein Problem ist, dass ich einen segfault beim Kompilieren bekomme und ich habe Probleme herauszufinden, wie die einzelnen Werte gedruckt werden, die von der rekursiven Funktion generiert werden.

Segmentation fault (core dumped) 

Hier ist das Hauptprogramm:

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


} 

Und das rekursive Teilprogramm:

.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 

Dies ist, was gcc mir gibt

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

Nach dem Label 'sonst:' haben Sie 4 Zeilen, aber dann gibt es nichts, um den Code zu beenden. Gibt es ein fehlendes "Ret"? Nach dem letzten "Call Binom" wird die CPU fortsetzen, was auch immer halb zufällige Daten im Speicher ausgeführt werden, und wird segfault, hängen oder allgemein falsch handeln. Sie sollten Ihren Code in einem Debugger ausführen. –

+0

Mein Verständnis war, dass, wenn das Binom aufgerufen wird, es in equalorzero oder oneoronedifferenz recurse, die ret in ihnen enthalten. - Ich werde ein Ret hinzufügen, um es davon abzuhalten. –

+0

Das behebt den segfault nicht - vielleicht hat er einen anderen behoben, ich bin mir sicher, dass ich am Ende ret benötigt habe, um das zu verhindern, was du erwähnt hast –

Antwort

1

Die beiden wichtigsten Fragen mit Ihrem Assembler-Code sind: 1) Sie fügen die Summe der beiden rekursiven Aufrufe hinzu oder geben sie zurück. 2) Sie speichern Ihre Locals nicht auf dem Stack, so dass sie durch die rekursiven Aufrufe gelöscht werden - Sie verwenden die falschen Werte, sobald Sie von den Aufrufen zurückkehren. Hier ist mein Nacharbeiten des Codes, sind nur einige der Änderungen aufgrund meines Schreibens dies unter OSX:

Das rekursive Unterprogramm:

.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 

Das Hauptprogramm:

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

Und die Ergebnisse :

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