2016-07-16 3 views
-2

모든 이항 계수를 반복적으로 계산하고 n = 10 인 모든 이항 계수를 인쇄하려면 몇 가지 코드 (주 : 어셈블리 x86의 서브 프로그램)를 작성했습니다 , 제한 m < = n.어셈블리 x86/C- 반복 이항 계수 Segfault/인쇄 파스칼 삼각형

그래서 기본적으로 n = 10에 대해 파스칼 삼각형을 출력하려고합니다. (삼각형의 전체 형식없이)

제 문제는 컴파일시 segfault가 발생하고 재귀 함수에 의해 생성 된 개별 값을 출력하는 방법을 알아 내려는 데 문제가 있다는 것입니다.

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


} 

그리고 재귀 서브 프로그램 :

Segmentation fault (core dumped) 

여기에 메인 프로그램 것은

.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

레이블이 'otherwise :'이면 네 줄이 있지만 그 다음에는 코드를 끝낼 수 없습니다. 'ret'가 누락 되었습니까? 마지막'call binom '이후에 CPU는 세미 임의의 데이터가 메모리에 남아있는 것을 계속해서 수행하고 segfault, hang 또는 일반적으로 잘못 작동합니다. 디버거에서 코드를 실행해야합니다. –

+0

저의 이해는 binom이 호출 될 때 equal이 0 또는 oneoronedifference로 재귀됩니다. - 그걸 막으려면 거기에 ret를 추가 할거야. –

+0

이것은 segfault를 수정하지 못했을 것입니다 - 어쩌면 그것은 다른 것을 고쳤습니다, 여러분이 언급 한 것을 막기 위해 마지막에 ret를해야한다고 확신합니다 –

답변

1

두 가지 주요 문제를주고 무엇인가 어셈블리 코드는 다음과 같습니다. 1) niether는 두 개의 재귀 호출의 합을 더하거나 리턴하지 않습니다. 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