从main函数调用函数时出现分段错误(生成的NASM代码)

时间:2014-10-29 17:14:57

标签: assembly compiler-construction nasm

我正在开发一个针对x86和amd64的编译器。我的编译器目前在64位计算机上运行良好。在32位我得到一个段错误。

一个简单的空程序(只有main方法)编译为以下程序集:

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 function@main[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

我做错了什么?

1 个答案:

答案 0 :(得分:0)

你甚至都没有设置ebp,这就是你出错的原因。标准函数序言由push ebp; mov ebp, esp组成。您不必遵循该模式,但如果您没有初始化ebp,那么您应该访问相对于esp的参数和本地人(并注意push更改的事实它)。

此外,要恢复堆栈指针,您需要添加它,而不是减去。这是用sub dword esp, dword 8替换add 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