尝试运行以下程序集程序时:
.globl start
start:
pushq $0x0
movq $0x1, %rax
subq $0x8, %rsp
int $0x80
我收到以下错误:
dyld: no writable segment
Trace/BPT trap
知道可能导致这种情况的原因是什么? 32位汇编中的类似程序运行良好。
答案 0 :(得分:9)
OSX现在要求您的可执行文件具有包含内容的可写数据段,因此它可以动态地重定位和链接您的代码。 Dunno为什么,可能是安全原因,可能是由于新的RIP寄存器。如果你在那里放一个.data段(有一些虚假的内容),你将避免“无可写段”错误。 IMO这是一个ld bug。
关于64位系统调用,您可以通过2种方式完成。 GCC风格,使用libSystem.dylib中的_syscall PROCEDURE或raw。 Raw使用syscall指令,而不是int 0x80陷阱。 “int 0x80”是64位的非法指令。
“GCC方法”将为您分类系统调用,因此您可以使用sys / syscall.h中的相同32位数字。但是如果你是原始的,你将不得不通过ORing它与类型id来分类它是什么样的系统调用。这是两者的一个例子。请注意,调用约定是不同的! (为NASM语法道歉;气体让我烦恼)
; assemble with
; nasm -f macho64 -o syscall64.o syscall64.asm && ld -lc -ldylib1.o -e start -o syscall64 syscall64.o
extern _syscall
global start
[section .text align=16]
start:
; do it gcc-style
mov rdi, 0x4 ; sys_write
mov rsi, 1 ; file descriptor
mov rdx, hello
mov rcx, size
call _syscall ; we're calling a procedure, not trapping.
;now let's do it raw
mov rax, 0x2000001 ; SYS_exit = 1 and is type 2 (bsd call)
mov rdi, 0 ; Exit success = 0
syscall ; faster than int 0x80, and legal!
[section .data align=16]
hello: db "hello 64-bit syscall!", 0x0a
size: equ $-hello
查看http://www.opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/syscall_sw.h以获取有关如何键入系统调用的更多信息。
答案 1 :(得分:2)
系统调用接口在32位和64位之间不同。首先,int $80
替换为syscall
,系统调用号码不同。您需要查找64位版本系统调用的文档。 Here是64位程序的示例。