0

I am having difficulties closing a file in nasm assembly on mac 64 bit. My goal is to make a file and write to it. For now I think that I opened the file the correct way. Now I need to close the file so that the file actually gets made. Here is my code so far.

global start
; default rel
section .text
    start:
        ;open
        mov rax, 0x2000005
        mov rdi, file     
        mov rsi, 1   
        syscall

        ;close
        mov rax, 0x2000006
        mov rdi, file ;I need to replace this line. With what though?
        syscall

        mov rax, 0x2000001       ;Exiting
        xor rdi, rdi         
        syscall          

section .data
    
    str: db "Hello world", 0
    strlen: equ $ - str
    file: db "test.txt"
    lenfile: equ $ - file

I did a bit of research before I posted this question. I need to get something called a file handler, I think thats what its called. Help would be greatly appreciated.

EDIT Answer:

;close
mov rdi, rax ;rax contains the file handler from the previous syscall. Moving it here before it gets cleared
mov rax, 0x2000006
syscall

Edit 2

;close
mov rdi, rax ;rax contains the file handler from the previous syscall. Moving it here before it gets cleared
mov rax, 0x2000006
mov rsi, 0x0201
syscall

Actual answer

Turns out that I needed to write the file path including the file and not just the file.

Edit 2 works btw.

Yoffdan
  • 68
  • 7
  • 3
    The `open` returned the file handle for you in `rax`. You might want to familiarize yourself with standard unix file handling before trying to write code in assembly. – Jester Oct 06 '21 at 22:16
  • How do I store the file handle? I am reseting ```rax``` when I am putting the mode which is 0x2000006. Do I put it in any other registers to save the file handle? – Yoffdan Oct 06 '21 at 23:28
  • 2
    Yes, you can move it into another register or save it in memory. For this code as you want it in `rdi` anyway, you can just transfer it there before you overwrite it. – Jester Oct 06 '21 at 23:40
  • Thanks! I'm pretty sure that It works but when I compile and run the program, no file in that directory is being created. Do you know why its not being created? Would I need to write something to the file first? – Yoffdan Oct 07 '21 at 00:12
  • 3
    You're passing 1 as the flags argument to `open`, which if https://github.com/st3fan/osx-10.9/blob/master/xnu-2422.1.72/bsd/sys/fcntl.h is correct would be `O_WRONLY`. If you want the file created, you need the `O_CREAT` bit as well. (Again, the `open(2)` man page should explain that!) Try `mov rsi, 0x0201`. – Nate Eldredge Oct 07 '21 at 05:03
  • @Nate Eldredge, That did not create a file. Is there anything that I can do to fix it. I wrote it in edit 2. However, if you are unsure, I am okay with doing a bit of research by myself. Where can I access the open(2) man page? – Yoffdan Oct 08 '21 at 20:22
  • https://developer.apple.com/documentation/os/reading_unix_manual_pages – Nate Eldredge Oct 08 '21 at 20:23
  • 2
    By the way, closing the file is not the issue here; the file is created as soon as you open it, and moreover it gets closed automatically when the process exits. So if the file is not getting created, the problem is with the `open`, not the `close`. It could be that the flags I suggested are not the right ones; I don't have a way to check that. Oh, when creating a file you do need to specify permissions in the third argument, so try something like `mov edx, 0644` before the `open` syscall. – Nate Eldredge Oct 08 '21 at 20:24
  • Thanks, thats good to know. – Yoffdan Oct 08 '21 at 20:25
  • Hey, I looked at that and then I ran the command ```man 2 open``` and I looked at the arguments again. I realized it was the path including the file and not the file name that I needed to write. Thank you very much for pointing out that it was something wrong with my ```open``` function. Thanks again! – Yoffdan Oct 08 '21 at 20:36
  • Sorry to bother you further, @NateEldredge but I have one last quick question. I have opened, wrote, and closed a file. However, by default the permissions have been set to none so I cannot open the file. I have been able to manually change the permission but I would like to set the permissions to read and write by default. Do you know how I would be able to do that? – Yoffdan Oct 08 '21 at 20:46
  • The permissions are the third argument I mentioned in my comment edit above (maybe you didn't see it). You put the permissions, as a bitmask, in `edx` before calling `open`. – Nate Eldredge Oct 08 '21 at 20:48
  • The filename by itself will suffice, and will create the file in the current working directory, if you have permission to do so. I am guessing you ran this in a directory where you did not have permission to create files, or else you ran the program in a different directory from the one where you were looking for the file. (IDEs have a habit of running programs in unexpected directories.) – Nate Eldredge Oct 08 '21 at 20:49
  • Sorry I did not see that. It does not work though. Are you sure its edx, @NateEldredge? – Yoffdan Oct 08 '21 at 20:59
  • 2
    It is edx on Linux, and my understanding is that MacOS follows the same conventions here. See also https://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-and-user-space-f. However, I do not have a MacOS system to test, so I can't be certain. – Nate Eldredge Oct 08 '21 at 21:04
  • 2
    Oh sorry, nasm has different syntax for octal, per https://stackoverflow.com/questions/39564402/how-to-represent-octal-numbers-in-assembly. Try `mov edx, 0o644`. Note you'll have to delete the file in order to recreate it with correct permissions. – Nate Eldredge Oct 08 '21 at 21:05
  • 2
    I'm pretty sure MacOS has some kind of system-call trace program similar to Linux `strace`. Yeah, `dtruss`. [How to trace system calls of a program in Mac OS X?](https://stackoverflow.com/q/31045575) So you can have it decode the args you're actually passing, and see the syscall return values. That's huge. (Note that MacOS's syscall ABI returns error/success by setting/clearing CF, not purely in-band signalling in RAX like Linux does.) – Peter Cordes Oct 08 '21 at 21:06
  • 1
    *Turns out that I needed to write the file path including the file and not just the file.* - That depends how you're running it. A bare filename is a relative path, relative to the current working directory (CWD) of your process. That depends on how it was run. If you `cd /tmp; ~/src/my_asm_program`, it will be exactly like doing `touch test.txt` there. Also, don't forget the `,0` terminator for the filename. That's needed, unlike on the data you're going to output with `write` where you pass a length instead of the kernel looking for a C string terminator. – Peter Cordes Oct 08 '21 at 21:10
  • Thanks @NateEldredge, it works. Do you know if it's possible to make 0o644 a number? If so what number? I've searched it up. Is it 420? Just tried it. 420 works! – Yoffdan Oct 08 '21 at 21:13
  • Thanks Peter Cordes! – Yoffdan Oct 08 '21 at 21:14
  • 1
    Yes, of course you can write it in decimal instead of octal if you want (and 420 is correct), but octal is conventional for permissions because you can work it out in your head. See https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation. That's what people reading your code are more likely to expect. – Nate Eldredge Oct 08 '21 at 21:42
  • Thank you so much for all answering all my long and annoying questions. – Yoffdan Oct 08 '21 at 22:08

0 Answers0