2016-07-15 1 views
-2

서브 프로그램에 segfault가 표시되는 이유를 디버깅하려고합니다.어셈블리 - 서브 프로그램이있는 Segfault

서브 프로그램 끝의 ret 줄에서 발생합니다. 한 번에 0x00 바이트가 문장의 끝에 도달하므로.

홈페이지 :

   .data 
string:   .string "aaaaaaaaaaa" 
endofstring: .space 8 
msg:   .string "%c occurs %d times \n" 

       .text 
       .global main 

main: 

    mov  $string,%rsi   #rsi = string storage 
    mov  $0x61, %ah    #storage of a 
    mov  $0x65, %al    #storage of e 
    mov  $0x69, %bh    #storage of i 
    mov  $0x6F, %bl    #storage of o 
    mov  $0x75, %ch    #storage of u 


#Case A 
    mov  %ah,%cl     #1 byte register for cmp later on. 
    mov  $0, %rax    #initialize count to 0 
    call FREQ     #Generate %rax value for 


    mov  %rax, %rdx    #count for printf (2nd argument) 
    mov  $msg, %rdi    #format for printf(1st argument) 
    mov  %r8, %rsi    #ch for printf (3rd argument) 

    xor  %rax, %rax    #reset %rax for printf output 

    call printf     #print the frequency value of the ch in string 


#Case E 
    mov  %al,%cl 
    mov  $0, %rax    #initialize count to 0 
    call FREQ 

    mov  %rax, %rdx    #count for printf (2nd argument) 
    mov  $msg, %rdi    #format for printf(1st argument) 
    mov  %r8, %rsi    #ch for printf (3rd argument) 

    xor  %rax, %rax    #reset %rax for printf output 

    call printf     #print the frequency value of the ch in string 

#Case O 
    mov  %bh,%cl 
    mov  $0, %rax    #initialize count to 0 
    call FREQ 

    mov  %rax, %rdx    #count for printf (2nd argument) 
    mov  $msg, %rdi    #format for printf(1st argument) 
    mov  %r8, %rsi    #ch for printf (3rd argument) 

    xor  %rax, %rax    #reset %rax for printf output 

    call printf     #print the frequency value of the ch in string 

#Case I 
    mov  %bl,%cl 
    mov  $0, %rax    #initialize count to 0 
    call FREQ 

    mov  %rax, %rdx    #count for printf (2nd argument) 
    mov  $msg, %rdi    #format for printf(1st argument) 
    mov  %r8, %rsi    #ch for printf (3rd argument) 

    xor  %rax, %rax    #reset %rax for printf output 

    call printf     #print the frequency value of the ch in string 
#Case U 
    mov  %ch,%cl 
    mov  $0, %rax    #initialize count to 0 
    call FREQ 

    mov  %rax, %rdx    #count for printf (2nd argument) 
    mov  $msg, %rdi    #format for printf(1st argument) 
    mov  %r8, %rsi    #ch for printf (3rd argument) 

    xor  %rax, %rax    #reset %rax for printf output 

    call printf     #print the frequency value of the ch in string 

    jmp done 


done: 

    ret 

서브 : 이런 이유

.text 
    .globl FREQ 



FREQ: 
    #subprogram body 
Start: 
    cmpb $0,8(%rsi)    #check for end of the string 
    je  donefreq 

loopfreq: 
    cmp  %cl, 8(%rsi)   #compare first string char with vowel 
    je  incrementstring   #if equal - jump to increment_string 
    add  $1, %rsi    #if not - increment string 
    jmp  Start     #jump to loop to check for end of string status/next char 

incrementstring: 
    add  $1, %rsi    #increment to next string character 
    add  $1, %rax    #add 1 to frequency of character 
    jmp  Start 

donefreq: 
    ret 

확실하지. - 디버깅이 조금 더 많은 정보를 주었으면 좋겠어. (

왜 이런 일이 일어나는가에 대한 생각을 갖고있는 사람은 누구인가? 나는 피 호출자 기능에 대한 내 노트의 윤곽을 정확히 따라 갔기 때문에 문제가있는 곳을 잃어 버렸다. 호출 수신자에

+0

서브 프로그램은 _RSP_에 계속 추가되므로 'ret'에 도달 할 때까지 리턴 주소는 no입니다. 스택의 적당한 위치에서 더 길어지고'ret'는 어떤 세미 임의 메모리 위치로 돌아 가려고하는 동안 충돌 할 것입니다. –

+0

'mov $ string, % rsp' 이것은 나도 아주 나쁘다. 스택이 작동하는 방식과 매개 변수 전달 방법에 대해 읽어야합니다. 코드에 심각한 문제가 있습니다. –

+0

그래서이 카운터를 유지하려면 RSP를 늘린 다음 RSP에서 RSP로 계산 한 횟수를 다시 계산해야합니다. –

답변

3

당신은 당신의 문자열에 대한 포인터로 %rsp을 사용할 수 없습니다. 당신은 너무 당신의 ret 명령은 일부 가짜 주소로 이동하려고 스택에 리턴 어드레스를 손상된다. %rsi 또는 다른 범용 레지스터를 사용합니다. 스택 포인터는 원하는대로 사용할 수있는 레지스터가 아닙니다.

+0

고마워요 - 이것으로 인해 혼란스러워졌습니다. 많은 감사를드립니다. 나는 magnificient @Jester가 제안한 것처럼 문자열 저장을 위해 $ rsi를 사용하도록 전환했습니다. 모든. –