2014-10-29 87 views
0

我正在開發一個針對x86和amd64的編譯器。我的編譯器在64位計算機上工作的非常好。在32位,我得到一個段錯誤。從主函數調用函數(生成的NASM代碼)時出現分段錯誤

一個簡單的空的程序(只是主要方法)編譯成以下組件:

extern GC_init 
global main 
global f_main 
segment .data 
segment .text 
main: 
    ; argc = dword [ebp+8] 
    ; argv = dword [ebp+12] 
    push edx 
    ; line 3 

    ; proceed GC_init[] 
    xor  dword eax, dword eax 
    call GC_init 
    ; line 4 

    ; proceed [email protected][argc, argv] 
    push dword [ebp+12] 
    push dword [ebp+8] 
    xor  dword eax, dword eax 
    call f_main 
    sub  dword esp, dword 8 

    pop  edx 
    ret 
f_main: 
    push edx 
    ; line 7 

    ; oax = 0 
    mov  dword eax, dword 0 
    ; line 8 

    .L0: 

    pop  edx 
    ret 

f_main是實際的主要方法。 main只需呼叫GC_init,然後f_main

我編譯和使用下列命令運行的代碼:

$ nasm -f elf -o test.o test.asm 
$ gcc -o etest test.o -lgc 
$ ./etest 
Segmentation fault (core dumped) 

我調試使用GDB程序,發現段錯誤來自於第二按壓指令(push dword [ebp+12])。

這裏是我的電腦的一些信息:

$ uname -a 
Linux [name] 3.13.0-37-generiC#64-Ubuntu SMP Mon Sep 22 21:30:01 UTC 2014 i686 athlon i686 GNU/Linux 

我在做什麼錯?

回答

0

你甚至沒有設置ebp,所以這就是爲什麼你會得到一個錯誤。標準功能序言由push ebp; mov ebp, esp組成。您不必遵循該模式,但如果您未初始化ebp,則應該訪問相對於esp的參數和當地人(並且請注意push更改它的事實)。

此外,要恢復堆棧指針,您需要添加到它,而不是減去。這是用add dword esp, dword 8代替sub dword esp, dword 8

一種可能實現的main可能看起來像:

sub esp, 12  ; allocate space for edx and 2 outgoing arguments 
mov [esp + 8], edx ; save edx 
xor eax, eax  ; I assume you have a special reason for this 
call GC_init 
mov eax, [esp + 16] 
mov [esp], eax  ; copy 1st argument 
mov eax, [esp + 20] 
mov [esp + 4], eax ; copy 2nd argument 
xor eax, eax 
call f_main 
mov edx, [esp + 8] ; restore edx 
add esp, 12  ; restore stack 
ret 
相關問題