2017-01-29 14 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" 

Почему функция argCount выполняется правильно, если аргумент count в командной строке не равен 2, но дает мне ошибку сегментации? По-видимому, общий поток управления программой работает некорректно. Возможно, что-то не так с прологом или эпилогом функции?Почему эта функция работает, но дает мне ошибку сегментации?

+0

Вы можете использовать 'jne' расшириться к функции' argCount' вместо 'call'. В сочетании с тем, что вы не использовали 'main' (что также неправильно), это приведет к сбою. На самом деле это сбой даже с 'main', потому что адрес возврата находится не в этом месте в стеке. – Jester

+0

jne является правильным, потому что я хочу, чтобы argCount выполнялся, если значение в eax не равно 2. – sdfsdfsdf

+0

Неправильно, потому что вы не можете 'jne' для функции (за исключением особых случаев). Либо сделайте это ярлыком внутри вашей текущей функции, либо перепишите код, чтобы вы могли «позвонить» ему. – Jester

ответ

0

Непосредственная проблема заключается в том, что ret в конце argCount идет не туда, потому что у него нет действительного обратного адреса.

Кроме того, вы должны использовать main, если вы намерены работать с libc, а также будьте осторожны, чтобы поддерживать выравнивание стека в соответствии с 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" 

Обязательно компилировать и компоновать с использованием gcc так что Libc вытягивается в должным образом, и поставить -m32, если вы на 64 битную среду для получения 32-разрядной программы (потому что этот код работает только как 32 бит).

0

Эти строки неправильны:

cmp $2, %eax 
jne argCount 

CALL делает две вещи:

  1. Нажмите адрес возврата в стек
  2. Перейти безусловно вызываемой функции.

Если вы используете Jcc или JMP инструкцию для вызова функции, вам нужно будет вручную нажать адрес возврата в стек для вашего кода, чтобы работать должным образом.

push return_address 
jmp argCount 
return_address: 

Это собирается вызвать проблемы, если вы используете условный переход, однако, так как, когда вы пишете код, который вы не можете предсказать, была ли или не принимать ветвь (и, следовательно, в RET в вызываемом функция уже вытащила адрес возврата из стека для вас, или вам нужно позаботиться об этом сами).

То, что вы должны делать:

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