尝试运行以下汇编程序时:
.globl start
start:
pushq $0x0
movq $0x1, %rax
subq $0x8, %rsp
int $0x80
我收到以下错误:
dyld: no writable segment
Trace/BPT trap
知道是什么原因造成的吗?32 位汇编中的类似程序运行良好。
尝试运行以下汇编程序时:
.globl start
start:
pushq $0x0
movq $0x1, %rax
subq $0x8, %rsp
int $0x80
我收到以下错误:
dyld: no writable segment
Trace/BPT trap
知道是什么原因造成的吗?32 位汇编中的类似程序运行良好。
OSX 现在要求你的可执行文件有一个可写的内容数据段,这样它就可以动态地重新定位和链接你的代码。不知道为什么,也许是安全原因,也许是因为新的 RIP 寄存器。如果您在其中放置一个 .data 段(带有一些虚假内容),您将避免“不可写段”错误。IMO 这是一个ld
错误。
关于 64 位系统调用,您可以通过 2 种方式进行。GCC 风格,它使用 _syscall PROCEDURE fromlibSystem.dylib
或 raw。Raw 使用syscall
指令,而不是int 0x80
陷阱。int 0x80
是 64 位的非法指令。
“GCC 方法”将为您对系统调用进行分类,因此您可以使用在 sys/syscall.h 中找到的相同的 32 位数字。但是,如果您使用原始方法,则必须通过将其与类型 id 进行 ORing 来分类它是哪种系统调用。这是两者的一个例子。请注意,调用约定是不同的!(这是NASM
语法,因为gas
让我烦恼)
; 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了解有关如何键入系统调用的更多信息。
系统调用接口在 32 位和 64 位之间是不同的。首先,int $80
被替换为syscall
和系统调用号不同。您将需要查找 64 位版本的系统调用的文档。下面是一个 64 位程序的示例。