Mac OS X下64位汇编与Linux下64位汇编的一些不同

1 首先系统调用号大大的不同;mac64和linux32的系统调用号也不同(虽然局部可能有相同)

2 mac64的系统调用号在:

/usr/include/sys/syscall.h

可以查到,但是调用的时候其值要加上0x2000000,可以写一个宏处理:

%define mk64 0x2000000+

使用方式如下:

mov rax,mk64 1      ;exit NO
mov rdi,0           ;error_code
syscall

3 如果在mac64下汇编要与C库相链接,所有extern符号名前要加下划线,包括入口点main:

extern _strerror
extern _printf
global _main
_main:

而linux64下汇编和C库链接的时候必须去掉符号前的下划线。

4 mac里的PIE(参考:http://blog.csdn.net/mydo/article/details/44906109),在直接使用绝对地址时会发出警告,如想去除警告,必须使用相对地址:

;mov rbx,addr
;上一条指令要换成下一条
lea rbx,[rel addr]
mov rsi,[rbx]

5 mac64下不允许将值赋到32位的绝对地址里去,比如以下指令出错:

mov [addr],rax

需要强制声明为64位地址或者改用相对地址:

mov [qword addr],rax    ;ok
mov [rel addr],rax      ;ok too

但linux64下无此限制。

6 mac64和linux64对系统调用的C库包装有所不同,尤其是处理系统调用返回值的时候;比如mmap调用,linux64 C库貌似不检查参数,而是依据syscall自身检查;而mac64在调用前会检查参数,如果参数有误,根本不会进行系统调用,直接设置errno,然后返回。再拿mmap来说,如果在mmap C库函数上设断点,那么在经过N次的fast_syscall_stub之后:

->  0x7fff8c4fc3b5 <+277>: callq  0x7fff8c4fd9e0            ; _dyld_fast_stub_entry(void*, long)

才会进入断点,所以要在fast_syscall_stub上设置条件断点,忽略前面N次的捕获(我测试的程序时或略前面28次),然后会进入kernel动态库中的mmap函数:

libsystem_kernel.dylib`mmap:
->  0x7fff8ad05a96 <+0>:   pushq  %rbp
    0x7fff8ad05a97 <+1>:   movq   %rsp, %rbp
    0x7fff8ad05a9a <+4>:   pushq  %r15
    0x7fff8ad05a9c <+6>:   pushq  %r14
    0x7fff8ad05a9e <+8>:   pushq  %r12
    0x7fff8ad05aa0 <+10>:  pushq  %rbx
    0x7fff8ad05aa1 <+11>:  movl   %r8d, %r15d
    0x7fff8ad05aa4 <+14>:  movq   %rsi, %r14

其对传入mmap的参数进行了检查,如果发现参数错误,不会调用真正的__mmap函数,而是设置错误码,然后根据不同的错误类型跳至对应的C库错误处理函数:

0x7fff8ad05b11 <+123>: movl   $0x16, %edi
    0x7fff8ad05b16 <+128>: callq  0x7fff8ad03c53            ; cerror_nocancel

下面是cerror_nocancel函数的反汇编:

libsystem_kernel.dylib`cerror_nocancel:
->  0x7fff8ad03c53 <+0>:  movl   %edi, -0x14a629d9(%rip)   ; errno
    0x7fff8ad03c59 <+6>:  movq   %gs:0x8, %rax
    0x7fff8ad03c62 <+15>: testq  %rax, %rax
    0x7fff8ad03c65 <+18>: je     0x7fff8ad03c69            ; <+22>
    0x7fff8ad03c67 <+20>: movl   %edi, (%rax)
    0x7fff8ad03c69 <+22>: movq   $-0x1, %rax
    0x7fff8ad03c70 <+29>: movq   $-0x1, %rdx
    0x7fff8ad03c77 <+36>: retq

而且最为关键的一点是,貌似mac64直接将系统调用错误码通过rax返回,而不像linux64那样返回的是错误码的补码。所以博文linux64汇编调用mmap的例子(博文链接:http://blog.csdn.net/mydo/article/details/45007989)里,syscall返回后的代码必须改写为如下代码:

    ;syscall for mmap
    syscall
    cmp rax,0xfff
    ja next
    push rax
    mov [rel errno],rax
    pop rax
    or rax,-1

7 暂时想到这么多不同点,未完待续

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。