2014-10-29 2 views
0

x86 및 amd64를 대상으로하는 컴파일러를 개발 중입니다. 제 컴파일러는 현재 64 비트 컴퓨터에서 잘 작동합니다. 32 비트에서 나는 segfault를 얻고 있습니다.main 함수에서 함수를 호출 할 때 분할 오류가 발생했습니다. (생성 된 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 실제 주요 방법이다. mainGC_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이 변경된다는 사실에 유의하십시오).

또한 스택 포인터를 복원하려면 빼기가 아닌 추가해야합니다. 이는 sub dword esp, dword 8add 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