2016-07-16 6 views
-1

GDB를 통해 실행하려고 시도하고 C 메인 프로그램이 주 기능으로 들어가면 분할 오류가 계속 발생합니다.C/어셈블리 서브 프로그램 세그먼트 화 오류

GDB 오류 :

Breakpoint 1, main() at binom_main.c:7 
7 n=10; 
(gdb) s 
10 0; 
(gdb) s 
12 +){ 
(gdb) s 

Program received signal SIGSEGV, Segmentation fault. 
0x00000000004005c4 in otherwise() 
(gdb) 

I는 다음과 같은 코드를 컴파일 :

as binom.s -o binom.o 
gcc -S -Og binom_main.c 
gcc -c binom_main.s  
gcc binom_main.o binom.o -o runtimes 

가 좀 더 효율적으로 여기 GDB를 사용하는 방법을 배우려고 노력하고있어하지만 이런 세그먼테이션 폴트 (segfault)이 매우 모호하고 제한 . 기능이 시작되는 순간이 segfault가 왜 발생합니까? 두 파일을 잘못 연결 했습니까?

홈페이지 :

#include <stdio.h> 

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

n=10; 
i=0; 


for (i=1; i<2;i++){ 

result = binom(n,i); 

printf("i=%d | %d \n", i, result); 

} 

return 0; 


} 

하위 : 디버그 ASM에 GDB를 사용할 때

.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 

    call printf 
    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 
    ret 
+1

실행 한 명령이 모두 있습니까? 두 개의'.o' 파일이 어디에 링크되어 있는지 나는 알 수 없습니다. 'gcc -o binom binom_main.o binom.o'와 같은 것을 할 필요가 있습니다. – kaylum

+1

두 번째보기에서 스택 오버플로 (하하)의 교과서 같은 소리가납니다. 당신이'otherwise()'에서 오류를 얻었음에 유의하여'main'을 입력하는 것이 옳지 않습니다. 추신 : 당신도'printf' 잘못 사용, 또는 기여 요인이되지 않을 수도 있습니다. – Jester

+0

@kaylum 네! 나는 그것을 OP에 포함하는 것을 잊었다. 나는 그것을 편집했다. 미안합니다. –

답변

2

이 해체 창뿐만 아니라 소스 창을 확인합니다. (예 : layout asm/layout reglayout next) 원하는 도움말을 얻을 때까지 태그 위키 하단에있는 도움말 및 문서 링크를 참조하십시오.

stepi (si)을 사용하면 C 문이 아닌 지침에 따라 단계별로 수행 할 수 있으며 반환하기 전에 무언가가 손상되어 asm 외부의 충돌을 조사 할 수 있습니다. (? 사소한)

sub  $1, %edi   #binom(n-1,m) 
call binom 
# at this point, %edi no longer holds n-1, and %esi no longer holds m. 
# because binom clobbers them. (This is normal) 

# as Jester points out, you also don't save the return value (%eax) from the first call anywhere. 
sub  $1, %esi   #binom(n-1,m-1) 
call binom 

또 다른 버그가 :

cmp  $0x01, %esi   #m=1? 
# but then you never read the flags that cmp set 

또 다른 심각한 버그 :

012,374


이 버그처럼 보인다

+0

어떻게 asm 프로그램을 시작 하시겠습니까? 나는 컴파일러'(gdb)에서 휴식을 얻는다. binom.s : 12 binom.s라는 이름의 소스 파일이 없다. '내가 단지 이것을 얻는다.'(gdb) si 0x000000000040054b 결과 = binom (n, i); ''si' gdb 명령에서. –

+0

@Egyptian_Coder : 일반 사람과 같은 디버그 기호로 컴파일하지 않는 이유는 무엇입니까? 'gcc -g binom_main.c -Og binom.S -o runtimes'는 하나의 명령으로 모든 것을 컴파일/어셈블 링/링크합니다. C 프리 프로세서가 필요하지 않더라도 손으로 직접 작성한 asm 소스를 위해'.S'를 추천합니다. –

+0

@Egyptian_Coder : 숫자 주소에 중단 점을 설정하려면'b * 0x000000000040054b'을 사용하십시오. (즉, 포인터와 같은 주소를 역 참조). 또한, 내가 본 것은 통화 설정의 일부인 지침 중 하나만 수행했기 때문입니다. 그래서 그것은'binom (n, i)'호출자 측의 명령입니다. 내가 제안한 것처럼 디스 어셈블리 창을 표시하도록 gdb를 설정했다면 이걸 보았을 것이다. asm 함수를 밟을 때까지 더 많은 단계를 거쳐야합니다. 또는 asm 함수로's'를 호출 한 다음, * 및 *를 통해 'si'를 출력합니다. –