2017-01-29 9 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

あなたが関数 'argCount'の代わりに、' call'に分岐する 'jne'を使用しています。あなたが '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は、2つのことを行います。

    関数を呼び出すためにJccまたはJMP命令を使用する場合は、あなたのコードが正しく動作するために、手動でスタックにリターンアドレスをプッシュする必要があります。

    push return_address 
    jmp argCount 
    return_address: 
    

    あなたがコードを書いているときに分岐が取られたかどうかを予測する(と呼ばにおけるのでRETすることはできませんので、あなたが、しかし、条件ジャンプを使用している場合、これは問題を引き起こすことが起こっています関数はすでにあなたのスタックから戻りアドレスをポップした、またはあなた自身の世話をする必要があります)。あなたがやるべきことは何

    は次のとおりです。

    cmp $2, %eax 
    je skip_argcount_call 
    call argCount 
    skip_argcount_call: 
    
  • 関連する問題