Search code examples
linuxassemblyx86-64nasmsystem-calls

How to read from and write to files using NASM for x86-64bit


I have a NASM program for 64bit Linux system which works with standard I/O devices and it looks something like that:

section .data

prompt      db  "Enter your text: ", 10
length      equ $ - prompt
text        times 255 db 0
textSize    equ $ - text    

section .text
global main
main:
    mov     rax, 1
    mov     rdi, 1
    mov     rsi, prompt
    mov     rdx, length
    syscall         ;print prompt

    mov     rax, 0
    mov     rdi, 0
    mov     rsi, text
    mov     rdx, textSize
    syscall         ;read text input from keyboard

    mov     rcx, rax  ; rcx  - character counter
    mov     rsi, text ; a pointer to the current character starting from the beginning.

   ****
exit:
    mov     rax, 60
    mov     rdi, 0
    syscall

I need the program to read from and write to the files, but I can't find anywhere which syscalls has to be used and how they should be used to achieve these results. So, I am wondering if someone of you could help me. Thanks in advance.


Solution

  • Use system calls "open" and "close":

    Open a file under 64-bit Linux:

    rax = 2
    rdi = pointer to NUL-terminated filename
    rsi = something like O_WRONLY  or  O_WRONLY|O_CREAT
    rdx = file flags if creating a file (e.g. 0644 = rw-r--r--)
    syscall
    now rax contains the file hanle
    

    Close a file:

    rax = 3
    rdi = file handle
    syscall
    

    Reading/writing from/to a file:

    rax = 0 or 1 (like keyboard/screen in/output)
    rdi = file handle (instead of 0/1)
    ...
    

    See Opening file modes in x86 assembly Linux for where to find definitions for the flags, e.g. in asm-generic/fcntl.h which defines them in octal. (NASM uses different syntax for octal literals than GAS and C; you want 0q100 rather than 0100.)

    O_RDONLY happens to be 0 on Linux, so it's the "default" if you forget to include one of O_RDONLY, O_WRONLY or O_RDWR. (The open(2) man page says the flags parameter must include one of the three.)

    Use strace ./my_program to decode the args you actually pass to system calls, and their return values (in RAX). A bad pointer will result in -EFAULT for example, or trying to write a read-only file descriptor will result in -EBADF.