Lance Pollard
Lance Pollard

Reputation: 79248

How do you create a file in assembly with a dynamically specified file path?

This question is mainly how to handle the pathname which is an arbitrarily long string, in assembly, without db or any helpers like that. I have seen several examples such as this which shows:

section .text
   global _start         ;must be declared for using gcc

_start:                  ;tell linker entry point
   ;create the file
   mov  eax, 8
   mov  ebx, file_name
   mov  ecx, 0777        ;read, write and execute by all
   int  0x80             ;call kernel

   section  .data
file_name db 'myfile.txt'

However, I would specifically like to understand how to do this dynamically. I would like to (1) better understand the requirements of the filename in terms of assembly (does it need a null terminator, etc.), and more importantly (2) specify the file name without the use of db or any assembler helpers. For example, you could specify the file name through the command line, and its structure would be unknown to the object file.

How do you do this?

Upvotes: 2

Views: 326

Answers (2)

Peter Cordes
Peter Cordes

Reputation: 364160

System calls that take a const char* without a length arg always take C strings: 0-terminated, implicit length.

Like open(const char *path, int flags, int mode), unlike write(int fd, void *buf, size_t len).

This is why they work when called from C like open("input.txt", O_RDONLY), or open(argv[1], O_WRONLY|O_CREAT). Remember that C string literals give you a pointer to an array of char in static storage with a 0 terminator.

BTW, NULL is a pointer constant. NUL is ASCII '\0'. Just call them "0 terminated" strings.


So yes, you should use , 0 at the end of your db.

Command-line args are always in this C-string format; it's how Unix passes around string data across system-call / process boundaries, as well as to ISO C standard library functions. This includes all pathnames.


In Linux, on entry to _start, the stack pointer points at argc. Above that are the elements of the char *argv[] array. (Not a char **argv pointer, just an array of values right there on the stack, from ESP+4 to ESP+argc*4. Also terminated by a NULL pointer (0)). This is documented in the i386 and x86-64 System V ABI docs.

Linux Assembly x86_64 create a file using command line parameters shows an example of loading argv[1] into the pathname arg of a system call.

Reading from a file in assembly is a 32-bit example.

Upvotes: 3

Just build the string in memory somehow (with a null terminator, as was pointed out in the comments), and then pass the pointer to it in place of file_name. To use a command-line argument, it's already built for you, so just point to it, like this: mov ebx, [esp + 8] (for reference, that's equivalent to argv[1]). By the way, in a real program, you should check argc (which lives at [esp]) before you do that to make sure it's at least 2.

Upvotes: 1

Related Questions