2016-07-07 9 views
0

をしながら、私は番号を記入手順を書いたので、私はMASM32の手順で作業する方法を学んでいる:SIGSEGV、セグメンテーションフォールト「RET」

.386 
.model flat, stdcall 
option casemap : none 

include \masm32\include\masm32.inc 
include \masm32\include\kernel32.inc 
include \masm32\macros\macros.asm 
includelib \masm32\lib\masm32.lib 
includelib \masm32\lib\kernel32.lib 

.data 
    number dw 397 
    temp db 10 
    symbol dw ? 
    i dw ? 

.code 
    printnumber proc num:WORD 
    mov ecx, 0 
    mov ax, num 
    @@: 
    mov edx, 0 
    div temp 
    mov bh, 0 
    mov bl, ah  
    push bx 
    inc cx 
    cmp al, 0 
    mov bl, al 
    mov ax, bx 
    jnz @B 
    mov i, cx 
    @@: 
    pop symbol 
    add symbol, 48 
    mov ax, symbol 
    print ADDR symbol 
    dec i 
    cmp i, 0 
    jnz @B 
    ret 
printnumber endp 

start: 
    push number 
    call printnumber 
    ret ;here program fails 
end start 

プログラム版画「397」に成功し、これにしようとした後に"ret"には問題があります: "Program received signal SIGSEGV、Segmentation fault。"私は何をすべきか?

+0

スタックをアンバランスにしました。あなたはあなたが押した '数字'を削除したい。 – Jester

答えて

0

スタックを適切にクリーニングしなかったため、スタックのバランスが崩れています。あなたのコードファイルの先頭に

、あなたはこのディレクティブを持っている:

.model flat, stdcall 

重要な部分は、あなたの関数が使用する呼び出し規約を指定するstdcall指示、です。これは、Windowsプログラムで最も一般的な呼び出し規約であり、Windows APIで使用されているのと同じものです。 stdcall呼び出し規約には、2つの重要な機能があります。

  1. 引数は右から左にスタックにプッシュされます。
  2. 返される前に、呼び出し先がスタックをクリーンアップする必要があります。

最初の機能は他の共通呼び出し規約cdeclと同じですが、2番目の機能はまったく反対です。この場合、あなたは間違っています。 (実際には、コードはスタックをまったくクリーンアップしないので、呼び出し規約に関係なく壊れてしまいます!)

基本的に、stdcall呼び出し規約を使用している場合は、ret instructionのバージョンを使用します引数として即座に取る。この引数は、スタックが戻ったときにスタックからポップするバイト数を指定します。あなたはret 2使用するので、この場合は

、あなたは、一つの引数、WORDサイズnumberを持っている:それはさておき

printnumber proc num:WORD 
    mov ecx, 0 
    mov ax, num 
    @@: 
    mov edx, 0 
    div temp 
    mov bh, 0 
    mov bl, ah  
    push bx 
    inc cx 
    cmp al, 0 
    mov bl, al 
    mov ax, bx 
    jnz @B 
    mov i, cx 
    @@: 
    pop symbol 
    add symbol, 48 
    mov ax, symbol 
    print ADDR symbol 
    dec i 
    cmp i, 0 
    jnz @B 
    ret 2   ; clean up the stack by popping 2 bytes, 
        ; since 2 bytes were pushed by the caller 
printnumber endp 

を、私はMASM32のstartエントリ・ポイントであることを信じコントロールをWindowsに戻すには、ExitProcessに電話する必要があります。

start: 
    push number 
    call printnumber 
    invoke ExitProcess, 0 
end start 

をしかし、私はこのことについて間違っている可能性:All the MASM32 samples私はdo it this wayを見てきました。私は実際にMASM32 SDKを使用しません。通常、エントリポイントはcdecl関数で、単にretで制御を戻します。

関連する問題