2017-01-29 5 views
0
.code32 
.text 


.globl _start 
_start: 

; .globl main 
    .extern printf 

    pushl %ebp 
    movl %esp, %ebp 
; subl $4, %esp 

    movl 4(%ebp), %eax 
; movl 12(%ebp), %ebx 
; movl $0, %ecx 

    cmp $2, %eax 
    jne argCount 

    pushl %eax 
    pushl $msg2 
    call printf 
    add $8, %esp 

    movl %ebp, %esp 
    popl %ebp 

; movl $1, %eax 
; movl $0, %ebx 
; int $0x80 
    call exit 

argCount: 
    pushl %ebp 
    movl %esp, %ebp 

    pushl $msg3 
    call printf 
    add $4, %esp 

    movl %ebp, %esp 
    popl %ebp 

    ret 


.data 

; .asciz "Arg = %s" 
    msg2: .asciz "Arg Count = %d\n" 
    msg3: .asciz "This program takes 1 argument -> sizeOfArray\n" 

명령 줄에서 인수 개수가 2가 아니고 나에게 세그먼트 오류가 발생하면 함수 argCount가 올바르게 실행되는 이유는 무엇입니까? 프로그램의 전반적인 제어 흐름이 올바르게 작동하지 않는 것 같습니다. 함수 프롤로그 또는 에필로그에 잘못된 것이있을 수 있습니까?이 기능은 작동하지만 세분화 오류가 발생하는 이유는 무엇입니까?

+0

. 당신이'main'을 사용하지 않았다는 사실과 결합하면 (충돌도 마찬가지입니다), 충돌로 이어질 것입니다. 실제로 반환 주소가 스택의 해당 위치에 있지 않기 때문에 'main'을 사용하더라도 충돌이 발생합니다. – Jester

+0

jax는 정확합니다. 왜냐하면 eax의 값이 2가 아닌 경우 argCount를 실행하기 만하면되기 때문입니다. – sdfsdfsdf

+0

특수한 상황을 제외하고는 함수에 'jne'할 수 없기 때문에 올바르지 않습니다. 현재 함수 내부에 레이블을 만들거나 코드를 다시 작성하여 호출 할 수 있습니다. – Jester

답변

0

즉각적인 문제는 argCount의 끝에있는 ret이 유효한 반송 주소가 없기 때문에 잘못된 위치로 이동한다는 것입니다.

또한 libc를 사용하려는 경우 main을 사용해야하며 ABI에 따라 필요한 스택 정렬을 유지해야합니다. 프레임 포인터를 사용하는 것은 선택 사항이며 일반적으로 도움이되지 않으므로 생략했습니다.

.globl main 
main:     # main because we use libc 
    subl $12, %esp  # stack alignment 
    movl 16(%esp), %eax # argc 
    cmpl $2, %eax 
    movl $msg3, (%esp) # preset for msg3 
    jne argCount  # if argc!=2 use that 
    movl $msg2, (%esp) # otherwise msg2 
    movl %eax, 4(%esp) # and argc 
argCount: 
    call printf   # print 
    call exit   # exit 

.data 
    msg2: .asciz "Arg Count = %d\n" 
    msg3: .asciz "This program takes 1 argument -> sizeOfArray\n" 

컴파일해야합니다 및 링크 그래서 libc의이 제대로 당겨 gcc를 사용하여, 당신은 32 비트 프로그램을 생산하기 위해 64 비트 환경에있는 경우 (-m32을 제공 : 여기

는 가능한 버전입니다 이 코드는 32 비트로 만 작동하기 때문에).

0

이 라인은 잘못 : 호출 된 함수에

  • 점프 무조건 스택에

    1. 밀어 반송 주소 :

      cmp $2, %eax 
      jne argCount 
      

      CALL 두 가지를 수행합니다.

    당신이 함수를 호출 할 Jcc 또는 JMP 명령을 사용하는 경우, 당신은 당신의 코드가 제대로 작동하려면 수동으로 스택에 리턴 어드레스를 밀어해야합니다. 당신은, 그러나 조건부 점프를 사용하는 경우

    push return_address 
    jmp argCount 
    return_address: 
    

    당신이 지점 호출에 RET을 촬영 (따라서되었는지 여부를 예측할 수 없습니다 당신이 코드를 작성할 때부터 문제가 발생할 것입니다 함수가 이미 스택에서 반환 주소를 팝했거나 사용자가 직접 처리해야합니다.

    당신이 일을해야하는 것입니다 : 당신은 함수`argCount` 대신`call`로 분기하는`jne`를 사용

    cmp $2, %eax 
    je skip_argcount_call 
    call argCount 
    skip_argcount_call: