5

尝试运行以下汇编程序时:

.globl start

start:
    pushq $0x0 
    movq $0x1, %rax
    subq $0x8, %rsp
    int $0x80

我收到以下错误:

dyld: no writable segment
Trace/BPT trap

知道是什么原因造成的吗?32 位汇编中的类似程序运行良好。

4

2 回答 2

10

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了解有关如何键入系统调用的更多信息。

于 2012-03-28T10:37:42.797 回答
2

系统调用接口在 32 位和 64 位之间是不同的。首先,int $80被替换为syscall和系统调用号不同。您将需要查找 64 位版本的系统调用的文档。下面是一个 64 位程序的示例。

于 2012-03-27T02:07:53.160 回答