標籤:mac-os-x linux 64位 彙編 nasm
1 首先系統調用號大大的不同;mac64和linux32的系統調用號也不同(雖然局部可能有相同)
2 mac64的系統調用號在:
/usr/include/sys/syscall.h
可以查到,但是調用的時候其值要加上0x2000000,可以寫一個宏處理:
%define mk64 0x2000000+
使用方式如下:
mov rax,mk64 1 ;exit NOmov rdi,0 ;error_codesyscall
3 如果在mac64下彙編要與C庫相連結,所有extern符號名前要加底線,包括進入點main:
extern _strerrorextern _printfglobal _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 ;okmov [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 暫時想到這麼多不同點,未完待續
Mac OS X下64位彙編與Linux下64位彙編的一些不同