mcandre
mcandre

Reputation: 24592

NASM Hello World either segfaults or bus errors in Mac OS X

I'm writing Hello World in NASM, and I can get it to echo Hello World to the console, but the program segfaults if I don't run it with Make.

Trace with Makefile:

$ make
nasm -f macho -o hello.o --prefix _ hello.asm
ld -o hello hello.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie
./hello
Hello World!

Trace with manual commands:

$ nasm -f macho -o hello.o --prefix _ hello.asm
$ ld -o hello hello.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie
$ ./hello 
Segmentation fault: 11

hello.asm:

[bits 32]

section .data

msg: db "Hello World!", 0

section .text

global start
extern puts
extern exit

start:

push msg
call puts
add esp, 4

push 0
call exit

Makefile:

# Linux defaults

FORMAT=-f elf
MINV=
ARCH=-arch i386
LIBS=
RUN=./
EXECUTABLE=hello
PREFIX=
ENTRY=
PIE=

# Windows
ifeq (${MSYSTEM},MINGW32)
    FORMAT=-f win32
    EXECUTABLE=hello.exe
    PREFIX=--prefix _
    ENTRY=-e _start
    ARCH=
    LIBS=c:/strawberry/c/i686-w64-mingw32/lib/crt2.o -Lc:/strawberry/c/i686-w64-mingw32/lib -lmingw32 -lmingwex -lmsvcrt -lkernel32
    ENTRY=
    RUN=
endif

# Mac OS X
ifeq ($(shell uname -s),Darwin)
    FORMAT=-f macho
    PREFIX=--prefix _
    ENTRY=-e _start
    LIBS=-lc
    MINV=-macosx_version_min 10.6
    PIE=-no_pie
endif

all: test

test: $(EXECUTABLE)
    $(RUN)$(EXECUTABLE)

$(EXECUTABLE): hello.o
    ld -o $(EXECUTABLE) hello.o $(ARCH) $(LIBS) $(MINV) $(ENTRY) $(PIE)

hello.o: hello.asm
    nasm $(FORMAT) -o hello.o $(PREFIX) hello.asm

clean:
    -rm $(EXECUTABLE)
    -rm hello.o

Specs:

Upvotes: 2

Views: 1538

Answers (2)

nneonneo
nneonneo

Reputation: 179382

You tore down your stack frame twice:

mov esp, ebp
pop ebp
...
leave

You only need one of those, since leave is equivalent to mov esp, ebp; pop ebp.

See http://michaux.ca/articles/assembly-hello-world-for-os-x for several example hello world programs. Note that all of them exit the program explicitly with

; 2a prepare the argument for the sys call to exit
push dword 0              ; exit status returned to the operating system

; 2b make the call to sys call to exit
mov eax, 0x1              ; system call number for exit
sub esp, 4                ; OS X (and BSD) system calls needs "extra space" on stack
int 0x80                  ; make the system call

because you cannot ret from an entry point (there's nothing to return to).

Also note that if you call the function main and don't supply the e option to ld, then libc's entry point will be called. In that case, it is permissible to ret since you will return control to libc (which calls exit on your behalf).

Upvotes: 2

Gunner
Gunner

Reputation: 5884

2 things, your hello world string is not NULL terminated and as I mentioned in another post, when you use C functions, you MUST adjust esp after each call

Upvotes: 3

Related Questions