Hiep Chelsea
Hiep Chelsea

Reputation: 67

Segmentation Fault when linking assembly program with `ld`

I have some Assembly codes as below: (max.s file)

.section .data
d1: .double 12.5
d2: .double 6.5

formatstr: .asciz "Max value is: %lf\n"

.section .text
.globl _start
_start:
    movsd d1,%xmm0
    movsd d2,%xmm1
    ucomisd %xmm1,%xmm0
    ja endif
then:
    movsd %xmm1,%xmm0
endif:
    mov $formatstr,%edi
    mov $1,%eax
    call printf
    call exit

When I compiled it:

as max.s -o max.o
ld -lc -dynamic-linker /lib/ld-linux.so.2 -o max max.o

Then no error occurred.

But when I ran this file by ./max then this following error occurred: Segmentation fault

Upvotes: 0

Views: 744

Answers (2)

Jeff Bell
Jeff Bell

Reputation: 113

You are calling exit(3) without passing a return value. The normal way to exit _start from assembler is with a sys_exit system call.

Personally I would use main instead of _start. That way you'll get all of the initialization and cleanup such as flushing the i/o and calling the on_exit code that comes for free with exit(3).

(The only reason you might use your own _start is if you wanted to avoid libc in order to have a smaller executable. There is a discussion of how to do this here https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free ).

Upvotes: 0

Employed Russian
Employed Russian

Reputation: 213935

The problem is that your program uses libc functions: printf and exit (in addition to ld-linux), without having properly initialized libc.

That initialization normally happens in _start, provided by libc itself in crt0.o.

You also mix ix86 and x86_64 calling conventions, and call printf incorrectly (this is likely the immediate cause of the crash). In 32-bit mode (which you are apparently using), parameters are passed on stack, not in registers.

As Jeff Bell, answered, either rename your _start to main and use gcc instead of ld to link your program (after fixing your source to use correct calling convention), or get rid of libc dependencies by implementing printf and exit yourself and not linking with ld-linux and -lc.

Upvotes: 2

Related Questions