2012-06-24 2 views
4

вот код (exit.s):базовая сборка не работает на Mac (x86_64 + Lion)?

.section .data, 
.section .text, 
.globl _start 
_start: 
    movl $1, %eax 
    movl $32, %ebx 
    syscall 

, когда я исполняю " as exit.s -o exit.o && ld exit.o -o exit -e _start && ./exit"

возвращение "Ошибка шины: 10" и выход "echo $?" является 138

I также попытался пример правильного ответа на этот вопрос: Process command line in Linux 64 bit

стил получить «ошибка шины» ...

+0

возможно дубликат [GNU Assembler (Mac OS X 64-бит): Незаконная инструкция: 4] (http://stackoverflow.com/questions/11178313/gnu-assembler-mac-os-x-64-bit-illegal-instruction-4) –

ответ

13

Во-первых, вы используете старое 32-битное соглашение о вызове ядра Linux в Mac OS X - это абсолютно не работает.

Во-вторых, системные вызовы в Mac OS X структурированы по-другому - все они имеют идентификатор ведущего класса и номер системного вызова. Класс может быть Mach, BSD или что-то еще (см. here в источнике XNU) и сдвигается на 24 бита влево. Обычные системные вызовы BSD имеют класс 2 и таким образом начинаются с 0x2000000. Салоны в классе 0: недействительный.

Согласно §A.2.1 из SysV AMD64 ABI, также следует Mac OS X, идентификатор (системного вызовов вместе со своим классом на XNU!) Идет в %rax (или к %eax как высокий 32 бит не используется на XNU). Кулачный аргумент идет в %rdi. Далее идет %rsi. И так далее. %rcx используется ядром, и его значение уничтожается, и поэтому все функции в libc.dyld сохраняют его в %r10 перед выполнением системных вызовов (аналогично макросу kernel_trap от syscall_sw.h).

В-третьих, участки кода в двойных Маха-O называются __text и не .text как и в Linux ELF, а также находиться в __TEXT сегменте, в совокупности называют (__TEXT,__text) (nasm автоматически переводит .text в зависимости от обстоятельств, если Маха-O, выбирается в качестве мишени тип объекта) - см. Mac OS X ABI Mach-O File Format Reference. Даже если вы правильно получаете инструкции по сборке, помещая их в неправильный сегмент/секцию, приводит к ошибке шины. Вы можете либо использовать директиву .section __TEXT,__text (см. here для директивного синтаксиса), либо вы также можете использовать (упрощенную) директиву .text, или вы можете отказаться от нее вообще, поскольку предполагается, что опция -n была поставлена ​​на as (см. Справочную страницу as).

В-четвертых, точка входа по умолчанию для Mach-O ld называется start (хотя, как вы уже догадались, это может быть изменено с помощью опции -e линкера).

Учитывая все вышесказанное, вы должны изменить свой источник ассемблере следующим образом:

; You could also add one of the following directives for completeness 
; .text 
; or 
; .section __TEXT,__text 

.globl start 
start: 
    movl $0x2000001, %eax 
    movl $32, %edi 
    syscall 

Вот она, работает, как ожидалось:

$ as -o exit.o exit.s; ld -o exit exit.o 
$ ./exit; echo $? 
32 
+0

благодарит за помощь! можно ли использовать -arch i386, чтобы 32-битная программа сборки работала?Я попробовал, но получаю «Незаконная инструкция: 4». как и вопрос, упомянутый Алексом, «http://stackoverflow.com/questions/11178313/gnu-assembler-mac-os-x-64-bit-illegal-instruction-4» Я не уверен, как его скомпилировать для 32-битного – springrider

+1

'syscall' не является допустимой 32-разрядной инструкцией. И в syscalls 'int $ 0x80' i386 используются аргументы стиля BSD, проходящие через стек. См. [Здесь] (http://osxbook.com/blog/2009/03/15/crafting-a-tiny-mach-o-executable/) или погружение [здесь] (http://fxr.watson.org/ FXR/источник/BSD/DEV/i386/systemcalls.c? v = XNU-1699.24.8 # L92). –

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