2014-11-29 1 views
0

Я некоторые коды, как показано ниже: Assembly (max.s файл)Сегментация Fault при компоновке программы сборки с `ld`

.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 затем произошла эта ошибка: сбой Сегментация

+0

Это программа для 64-разрядной Linux. Поскольку у вас нет ошибки из 'ld', я думаю, вы пытались построить ее на 32-битной системе. – rkhb

+0

Да. Этот код принадлежит моему учителю. Он собрал его на класс и, конечно же, побежал. Я пошел домой и повторно использовал этот код и не работал, потому что я не думаю, что 32 бит отличается от 64 бит. –

+1

Существуют существенные различия между 32 бит и 64 бит. В вашем случае вы наткнулись на вызывающие соглашения: [cdecl (32bit - ваша система)] (http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) и [System_V_AMD64 (64 бит - система учителя)] (http: //en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI) – rkhb

ответ

0

Вы вызываете выход (3) без прохождения возвращаемого значения. Обычный способ выхода из _start с ассемблера - это системный вызов sys_exit.

Лично я бы использовал основной вместо _start. Таким образом вы получите всю инициализацию и очистку, такие как очистка ввода-вывода и вызов кода on_exit, который поставляется бесплатно с выходом (3).

(Единственная причина, по которой вы можете использовать свой собственный _start, - это если вы хотите избежать libc, чтобы иметь меньший исполняемый файл. Обсуждается, как это сделать здесь https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free).

+1

Вызов 'exit' без передачи значения вызовет случайный мусор для кода выхода, но не' SIGSEGV'. Остальные ваши советы хороши, хотя. –

2

Проблема заключается в том, что ваша программа использует libc функции: printf и exit (в дополнение к ld-linux), не имея надлежащим образом инициализируется libc.

Эта инициализация обычно происходит в _start, предоставленная libc сама по себе в crt0.o.

Вы также смешиваете ix86 и x86_64 вызывающие соглашения и неправильно вызываете printf (это, вероятно, является непосредственной причиной аварии). В 32-битном режиме (который вы, по-видимому, используете) параметры передаются в стеке, а не в регистры.

Как Джефф Белл, ответил, либо переименовать _start в main и использовать gcc вместо ld связать свою программу (после фиксации вашего источника использовать правильное соглашение о вызовах), или избавиться от libc зависимости от реализации printf и exit себя и не связывается с ld-linux и -lc.

+0

Можете ли вы рассказать мне, как исправить свой источник, чтобы использовать правильное соглашение о вызове? –

Смежные вопросы