Home > Blockchain >  How to correctly use the "write" syscall on MacOS to print to stdout?
How to correctly use the "write" syscall on MacOS to print to stdout?

Time:12-26

I have looked at similar questions, but cannot seem to find what is wrong with my code.

I am attempting to make the "write" syscall on MacOS to print a string to standard output.

I am able to do it with printf perfectly, and am familiar with calling other functions in x64 assembly.

This is, however, my first attempt at a syscall.

I am using GCC's GAS assembler.

This is my code:

.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"

There does not seem to be any error; there is simply nothing written to stdout.

I know that start is usually used as the starting point for an executable on MacOS, but it does not compile with GCC.

CodePudding user response:

You are using the incorrect SYSCALL number for MacOS. The base for the user system calls is 0x2000000. You are incorrectly using 0x2000000. As a result you have encoded the write SYSCALL as $0x20000004 when it should have been $0x2000004 (one less zero)

As a rule of thumb, make sure you are using the correct value for the the SYSCALL number in the %rax register; ensure you are using the correct arguments for the write SYSCALL. The write SYSCALL expects the following arguments:

  • %rdi: file descriptor to write to (e.g. 1 for standard output)
  • %rsi: pointer to the buffer containing the data to be written
  • %rdx: number of bytes to be written
  • On macOS, you need to use the syscall instruction to invoke a system call.
  • Related