section .data msg db 'This is a test', 10, 0 ; something stupid here ft db 'addr is %x',10,0section .text global _main extern _printf extern _exit_main: push rbp mov rbp, rsp ;xor al, al mov rdi, ft ;lea rdi,[rel ft] mov rsi,rdi call _printf ;xor rax,rax ;mov [rax],rax xor rdi,rdi call _exit ;mov rsp, rbp ;pop rbp ret
mac OS X 10.8.3:
nasm -f macho x.asm
gcc -o x x.o
会出现警告:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _main from a.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
由于安全问题,解释如下:
所谓的PIE是指position independent executable,即地址无关exe,换句话说也就是生成的机器码中不能出现lea rax, some_symbol_name这样的绝对寻址,而只能以:lea rax, [rel some_symbol_name]这种形式出现,目的是为了提高安全性,这样OS可以以随机的地址加载exe。
采用相对地址定位即可:使用第16行指令代替。
x64 API接口有用的提示:
Mac OS X complies to the System V ABI - AMD64 Architecture Processor Supplement. It mandates that the fist 6 integer/pointer arguments are passed in RDI
, RSI
, RDX
, RCX
, R8
and R9
, exactly in that order. The first 8 floating-point or vector arguments go into XMM0
, XMM1
, ..., XMM7
. Only after all the available registers are depleted or there are arguments that cannot fit in any of those registers (e.g. a 80-bit long double
value) the stack is used. 64-bit pushes are performed using MOV
(the QWORD
variant) and not PUSH
. Simple return values are passed back in the RAX
register. The caller must also provide stack space for the callee to save some of the registers.
printf
is a special function because it takes variable number of arguments. When calling such functions RAX
should be set to the number of floating-point arguments, passed in the vector registers. Also note that RIP
-relative addressing is preferred for data that lies within 2 GiB of the code.