basic assembly not working on Mac (x86_64+Lion)?

前端 未结 2 603
梦如初夏
梦如初夏 2020-12-01 20:16

here is the code(exit.s):

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

when I exe

2条回答
  •  有刺的猬
    2020-12-01 20:38

    First, you are using old 32-bit Linux kernel calling convention on Mac OS X - this absolutely doesn't work.

    Second, syscalls in Mac OS X are structured in a different way - they all have a leading class identifier and a syscall number. The class can be Mach, BSD or something else (see here in the XNU source) and is shifted 24 bits to the left. Normal BSD syscalls have class 2 and thus begin from 0x2000000. Syscalls in class 0 are invalid.

    As per §A.2.1 of the SysV AMD64 ABI, also followed by Mac OS X, syscall id (together with its class on XNU!) goes to %rax (or to %eax as the high 32 bits are unused on XNU). The fist argument goes in %rdi. Next goes to %rsi. And so on. %rcx is used by the kernel and its value is destroyed and that's why all functions in libc.dyld save it into %r10 before making syscalls (similarly to the kernel_trap macro from syscall_sw.h).

    Third, code sections in Mach-O binaries are called __text and not .text as in Linux ELF and also reside in the __TEXT segment, collectively referred as (__TEXT,__text) (nasm automatically translates .text as appropriate if Mach-O is selected as target object type) - see the Mac OS X ABI Mach-O File Format Reference. Even if you get the assembly instructions right, putting them in the wrong segment/section leads to bus error. You can either use the .section __TEXT,__text directive (see here for directive syntax) or you can also use the (simpler) .text directive, or you can drop it altogether since it is assumed if no -n option was supplied to as (see the manpage of as).

    Fourth, the default entry point for the Mach-O ld is called start (although, as you've already figured it out, it can be changed via the -e linker option).

    Given all the above you should modify your assembler source to read as follows:

    ; 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
    

    Here it is, working as expected:

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

提交回复
热议问题