如何在MacOS上正确使用"write"系统调用来将内容打印到标准输出(stdout)?

5

我已经查看了类似的问题,但似乎找不到我的代码出了什么问题。

我正在尝试在MacOS上进行“write”系统调用,以将字符串打印到标准输出。

我能够使用printf完美地完成此操作,并且熟悉在x64汇编中调用其他函数。

然而,这是我第一次尝试使用syscall

我正在使用GCC的GAS汇编器。

这是我的代码:

.section __TEXT,__text

.globl _main

_main:
    pushq %rbp
    movq %rsp, %rbp

    subq $32, %rsp

    movq $0x20000004, %rax
    movq $1, %rdi
    leaq syscall_str(%rip), %rsi
    movq $25, %rdx
    syscall

    jc error

    xorq %rax, %rax

    leave
    ret

error:
    movq $1, %rax
    leave
    ret

.section __DATA,__data
syscall_str:
    .asciz "Printed with a syscall.\n"

看起来没有任何错误;只是没有将任何内容写入stdout

我知道在MacOS上,start通常用作可执行文件的起始点,但它无法与GCC编译。


1
如果它没有编译/汇编/链接,那么应该会有一个错误消息。它是什么? - fuz
3
我认为 movq $0x20000004, %rax 应该是 movq $0x2000004, %rax(少一个0) - Michael Petch
1
@GregorHartlWatters 尝试使用“-nostdlib -nostartfiles”链接。 - fuz
2
@GregorHartlWatters 同时尝试使用 dtruss 跟踪程序的系统调用。 - fuz
1
@GregorHartlWatters:我修改了JavadIbrahimli的答案以明确指出你的错误。你可以接受这个答案。节日快乐! - Michael Petch
显示剩余4条评论
1个回答

6

您在MacOS中使用了错误的SYSCALL号码。用户系统调用的基数是0x2000000。您正在错误地使用该基数。因此,您已将write SYSCALL编码为$0x20000004,而实际应该是$0x2000004(少一个零)

通常情况下,请确保在%rax寄存器中使用正确的SYSCALL编号;确保您使用了write SYSCALL的正确参数。 write SYSCALL需要以下参数:

  • %rdi:要写入的文件描述符(例如,标准输出为1)
  • %rsi:指向包含要写入的数据的缓冲区的指针
  • %rdx:要写入的字节数
  • 在macOS上,您需要使用syscall指令来调用系统调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接