NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: paml27 on December 05, 2019, 12:35:24 AM
-
I created a file in 64-bit NASM on Linux. Now I want to open it and write data into it. The file is created, but no data are written. My code follows:
File_Name: db '/opt/Test_Output_Files/Linux_File_Test',0
File_Mode: dq 754
Write_Buffer: db 'This is what I want to write',0
; Create file
mov rax,85 ; sys_creat
mov rdi,File_Name
mov rsi,File_Mode ; mode (permissions)
syscall
mov rax,1 ; sys_open
mov rdi,File_Name
mov rsi,2 ;read-write
mov rdx,754
syscall
mov rax,1 ; sys_write
mov rdi,File_Name
mov rsi,Write_Buffer
mov rdx,29
syscall
mov rax,3 ; sys_close
mov rdi,File_Name
syscall
My questions are:
1. When I create a file in 64-bit Linux is it open for reading and writing, or do I need to issue an open command as well?
2. When I open a file in 64-bit Linux, what are the flags? According to the Linux man page at https://linux.die.net/man/3/open, there are three options:
O_RDONLY - Open for reading only.
O_WRONLY - Open for writing only.
O_RDWR - Open for reading and writing. The result is undefined if this flag is applied to a FIFO.
I know that read-only is zero, so I assumed write only and read-write are 1 and 2, but I haven't found any listing of the numeric values that we would use in assembly language, unlike the mode which is based on chmod.
3. I am doing all of this as a superuser, not as root. Any special considerations for file handling by a superuser?
Thanks very much for any help on this.
-
Hi Pam127,
I don't know much 64 bit code, but a few observations...
I think mode is supposed to be octal. C takes a leading zero to be octal, Nasm does not. You probably want "754q".
mov rax, 1 ; sys_open
mov rax, 1 ; sys_write
These can't both be right.
sys_create and/or sys_open should return a file descriptor in rax. Use that instead of filename from then on.
1) Dunno. What happens?
2) Dunno. I think "2" is correct. What happens?
3) Is there a difference? I don't think so.
Don't forget to exit cleanly when you're done.
Good luck. Let us know how it comes out.
Best,
Frank
-
Thanks for your reply, Frank. Yes, sys_open is 2, not 1. I've tried your other suggestions, but still no luck. I'm still working on this, so I'll let you know what happens.
-
A little more info. Sys_creat (as shown above) returns a positive value, and sys_write works with that. But I'm still having problems with sys_open. The flags may be the problem. The Linux man pages at http://man7.org/linux/man-pages/man2/open.2.html don't help much, and I haven't found any definitive source yet. The following code works, but sys_open still does not.
; Create file
mov rax,85 ; sys_creat
mov rdi,File_Name
mov rsi,File_Mode ; mode (permissions)
syscall
mov rdi,rax ; return code from sys_open
mov rax,1 ; sys_write
;mov rdi,File_Name
mov rsi,Write_Buffer
mov rdx,29
syscall
-
The answer to this question is:
; Create file
mov rax,85 ; sys_creat
mov rdi,File_Name
mov rsi,[File_Mode] ; mode (permissions)
syscall
The File_Mode variable must be passed by value (enclosed on brackets), not by reference, as it was before.
-
syscalls (x86-64) (https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/)
-
I was trying to do this and crossed this topic a couple of days ago. Today I managed to do it, and I know this thread is old, but I created an account just to leave the answer here for future students. After a lot of trial and error I figured 2 things:
- The flags starting with O_ are somewhere in the asm files, I don't remember which file, but can be found with a simple searching script looking for the same names that appear in the docs. The equivalent to creat() is 1101o, in octal.
- The mode flags shown in the documentation are also in octal, the default would be 644o, as in I can read and write and the rest can read.
Imma leave a little working program here as an example, hope it helps someone!
https://github.com/JaoCR/asm-examples/blob/master/file/file.asm (https://github.com/JaoCR/asm-examples/blob/master/file/file.asm)
EDIT: corrected flags, see replies bellow
-
Hi j40.
Welcome to the forum!
Thanks for the working example. Always welcome!
One observation:
fd_new: resb 1
... sounds a little short to me. I"d reserve at least a dword for a file descriptor. Since it"s the last variable in your program it won't cause a problem, but if you added another it would.
Best,
Frank
-
Thanks Frank! Changed the example to reserve a quad just to make sure.
-
Tip: glibc have wrapers around syscalls like, open(), read(), write(), create(), close()... The list of arguments are the same as the regular syscalls and follows the same calling convenction (except RCX is substituted by R10). If you take a look at 'man creat' and 'man open' you'll see that creat() is the same as open(), except the flags O_CREAT|O_WRONLY|O_TRUNC is assumed for the last one... Both functions will return a positive value (file descriptor) or negative (-1) in case of error (in EAX)...
Then, you can use open() to open/create a file using O_CREAT|O_RDWR|O_TRUNC if you want to be able to read/write the "new" file... and, take a look at the function prototype:
int open( const char *fname, int flags, mode_t mode );
Where `mode_t` is a typedef to 'int`... Using 'int' means you don't need the upper half of R?? registers, so you can write:
; test.asm
;
; Compiling and linking:
;
; nasm -felf64 -o test.o test.asm
; ld -s -o test test.o
;
bits 64
default rel
%define SYS_WRITE 1
%define SYS_OPEN 2
%define SYS_CLOSE 3
%define SYS_EXIT 60
%define STDERR_FILENO 2
; See with 'gcc -dM -E -include unistd.h - < /dev/null | grep O_'
%define O_CREAT 0o100
%define O_TRUNC 0o1000
%define O_RDWR 0o02
section .rodata
fname:
db "myfile.txt",0
errmsg1:
db `Cannot open/create file.\n`
errmsg1_len equ $ - errmsg1
errmsg2:
db `Error writing to file.\n`
errmsg2_len equ $ - errmsg2
buffer:
db `This should be writen to the file.\n`
buffer_len equ $ - buffer
section .text
global _start
_start:
; Try to open/create a file...
mov eax,SYS_OPEN
lea rdi,[fname] ; fname
mov esi,O_CREAT | O_RDWR | O_TRUNC ; flags
mov edx,0o0644 ; permission (in octal).
syscall
test eax,eax ; is the file descriptro negative?
jns .continue ; no? continue. yes? then...
; ... print error message...
lea rsi,[errmsg1]
mov edx,errmsg1_len
.printerr_exit:
mov edi,STDERR_FILENO
mov eax,SYS_WRITE
syscall
; ...and exit with error 1.
mov eax,SYS_EXIT
mov edi,1
syscall
.continue:
mov ebx,eax ; store fd in EBX (Preserved bewteen calls).
; Try to write a string to the file.
mov edi,eax ; Put file descriptor in EDI.
mov eax,SYS_WRITE
lea rsi,[buffer]
mov edx,buffer_len
syscall
test eax,eax ; write retuns -1 in case of error. Is it negative?
jns .continue2 ; no? continue. yes, then...
; ...close the file...
mov eax,SYS_CLOSE
mov edi,ebx
syscall
; ... and print error messgae and exit with 1.
lea rsi,[errmsg2]
mov edx,errmsg2_len
jmp .printerr_exit
.continue2:
; Close the file and exit with 0.
mov eax,SYS_CLOSE
mov edi,ebx
syscall
mov eax,SYS_EXIT
xor edi,edi
syscall
-
Valeu Pissarra! You made me realize I was thinking wrong about the flags. I was using decimal base, but accidentally placed an extra zero which somehow managed to generate the same result as the correct flags. The command you shown did not show the flags in my system, but I changed to the correct one in octal, 1101o as in your function, and it also works fine. Should be the correct way to do this. I updated the example on my github already, thanks guys!
-
Valeu Pissarra! You made me realize I was thinking wrong about the flags. I was using decimal base, but accidentally placed an extra zero which somehow managed to generate the same result as the correct flags.
"Valeu"? Are you brazilian? I am from Vitória/ES!
Anyway... glad to help! :)
-
Yep, Sao Carlos, SP. Valeu mesmo! To entregando o trabalho agora inclusive kkkkk
-
Yep, Sao Carlos, SP. Valeu mesmo! To entregando o trabalho agora inclusive kkkkk
Jóia... Eu também tive esse problema com octal no NASM (prefixando com 0, como em C) até ver a documentação.
Quanto às permissões... tenha em mente que pode ser necessário manipular umask também.
To the benefict of the english readers: "Nice... I had this problem with octals in NASM too (using que 0 prefix, as in C) until I read the documentation. As for the permissions... keep in mind that it could be necessary to deal with umask too."
[]s
Fred