2014-10-29 39 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