1

私はbisonを使用してコンパイラを作成し、プロシージャを実装しようとしています。オンラインで「globalintpow」の例を見つけましたが、これはまったく問題なく機能し、それをモデルにした独自のプロシージャ呼び出しを行いました。このコードスニペットの関数「bar」は、1つの整数パラメーターのみを受け取り、それを出力します。コンパイルしたプログラムを実行して実行すると、次のようになります。

-intpowは想定どおりに実行され、通常のプログラム終了では、「bar」が宣言された関数は想定どおりに実行され、通常の関数終了になりますが、barを呼び出すと(したがって、次の3行を追加します)バーコールに固有のコメント)、プログラムは、セグメンテーション違反が発生する最後まで、想定どおりに実行されます。

gdbは、それが__bar_endの最後のポップebpにあると言います...なぜこれがsegfaultingなのですか?

extern printf
extern scanf
extern pow
SECTION .data
printf_int:
    db "%d", 10, 0
printf_float:
    db "%lf", 10, 0
printf_str:
    db "%s", 10, 0
scan_int:
    db "%d", 0
scan_float:
    db "%lf", 0
esp_tmp:
    dd 0

SECTION .text
global intpow
intpow:
    push    ebp
    mov     ebp,esp
    mov     eax,[ebp+12]
    mov     ebx,[ebp+12]
    mov     ecx,[ebp+8]

loop:
    cmp     ecx,1
    cmp     ecx,1
    jle     finish
    dec     ecx
    imul    eax,ebx
    jmp     loop

finish:
    mov     esp,ebp
    pop     ebp
    ret
global main
main:
    push    ebp
    mov     ebp,esp
    jmp     __bar_END
global __bar
__bar:
    push    ebp
    mov     ebp,esp
    sub     esp,-4
    push    DWORD [ebp + 8]
    push    DWORD printf_int
    mov     [esp_tmp], esp
    add     DWORD [esp_tmp], 8
    call    printf
    mov     esp, DWORD [esp_tmp]
    mov     esp,ebp
    pop     ebp
    ret
__bar_END:
    push    DWORD 12 #Unique to bar call
    call    __bar    #unique to bar call
    add     esp,4    #unique to bar call
    push    DWORD str0
    push    DWORD printf_str
    mov     [esp_tmp], esp
    add     DWORD [esp_tmp],8
    call    printf
    mov     esp, DWORD [esp_tmp]
    mov     esp, ebp
    pop     ebp
    ret

SECTION .data

global_vars:    times 0 db 0

true:   db "true",0
false:  db "false",0
str0:   db "hello world",0
4

1 に答える 1

2

問題はsub esp, -4です。スタックポインタを上に移動します(負の数を引くと加算されます)。スペースを使用していないため、スペースを割り当てる必要はありません。今、残りの混乱を片付けに行きます;)

于 2012-11-22T00:20:21.890 に答える