How to correctly use the "write" syscall on MacOS to print to stdout?
Asked Answered
D

1

6

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.

Deka answered 25/12, 2022 at 14:13 Comment(9)
If it did not compile/assemble/link, there should have been an error message. What was it?Sora
@Sora it does compile, but when I run it, nothing is written to stdoutDeka
@Sora if you're referring to the compilation error when trying to compile with start as the entry point, it is: "Undefined symbols for architecture x86_64: "_main", referenced from: implicit entry/start for main executable ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)"Deka
I think movq $0x20000004, %rax should be movq $0x2000004, %rax (one less 0)Balcony
@GregorHartlWatters Try to link with -nostdlib -nostartfiles.Sora
@GregorHartlWatters Also try to use dtruss to trace the system calls of the program.Sora
@MichaelPetch aghhhhh!!!! YES!!!! That was it!!!! Thank you so much! 2 has to be shifted left by 24 bits (2 << 24) and not by 28 which is what I was effectively doing. If you make your comment into an answer I would happily accept it. Thanks againDeka
@Sora thanks for the suggestions, I will look into them. and merry christmas!Deka
@GregorHartlWatters : I have amended Javadİbrahimli answer to explicit state what your error was. You can accept that answer. Happy holidays!Balcony
R
7

You are using the incorrect SYSCALL number for MacOS. The base for the user system calls is 0x2000000. You are incorrectly using that base. 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 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.
Righthand answered 25/12, 2022 at 14:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.