链接汇编程序与`ld`时的分段错误

时间:2014-11-29 18:26:14

标签: assembly segmentation-fault

我有一些汇编代码如下:(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

编译时:

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

然后没有发生错误。

但是当我按./max运行此文件时,发生以下错误:分段错误

2 个答案:

答案 0 :(得分:2)

问题是,您的计划使用libc个功能:printfexit(除了ld-linux),而没有正确初始化libc。< / p>

初始化通常发生在_start,由libc本身在crt0.o中提供。

您还混合ix86x86_64调用约定,并错误地调用printf(这可能是导致崩溃的直接原因)。在32位模式(您显然使用它)中,参数在堆栈上传递,而不是在寄存器中传递。

正如杰夫贝尔回答的那样,要么将您的_start重命名为main并使用gcc代替ld来关联您的计划(修复您的来源以使用正确的通话后)通过自己实现libcprintf而不是与exitld-linux链接来摆脱-lc依赖关系。

答案 1 :(得分:0)

您正在调用exit(3)而不传递返回值。从汇编程序退出_start的常规方法是使用sys_exit系统调用。

我个人会使用 main 而不是 _start 。这样你就可以获得所有的初始化和清理工作,例如刷新i / o并使用exit(3)调用免费提供的on_exit代码。

(您可能使用自己的_start的唯一原因是,如果您想要避免使用libc以获得较小的可执行文件。这里讨论了如何执行此操作https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free)。