如何使用动态指定的文件路径在程序集中创建文件?
How do you create a file in assembly with a dynamically specified file path?
这个问题主要是如何在没有 db
或类似的助手的情况下,如何在汇编中处理任意长字符串的路径名。我看过几个例子,例如 this 显示:
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'
但是,我特别想了解如何动态地执行此操作。我想(1)更好地理解文件名在汇编方面的要求(是否需要空终止符等),更重要的是(2)指定文件名 without 使用 db
或任何汇编助手。例如,您可以通过命令行指定文件名,目标文件将不知道其结构。
你是怎么做到的?
只需以某种方式在内存中构建字符串(使用空终止符,正如评论中指出的那样),然后将指针传递给它以代替 file_name
。要使用命令行参数,它已经为您构建,所以只需指向它,如下所示:mov ebx, [esp + 8]
(作为参考,相当于 argv[1]
)。顺便说一句,在实际程序中,您应该在执行此操作之前检查 argc
(位于 [esp]
)以确保它至少为 2.
采用 const char*
且没有长度 arg 的系统调用始终采用 C 字符串:0 终止,隐式长度 。
喜欢open(const char *path, int flags, int mode)
,不喜欢write(int fd, void *buf, size_t len)
。
这就是它们在从 C 调用时起作用的原因,例如 open("input.txt", O_RDONLY)
或 open(argv[1], O_WRONLY|O_CREAT)
。请记住,C 字符串文字为您提供了一个指向静态存储中 char
数组的指针,并带有 0
终止符。
顺便说一句,NULL 是一个指针常量。 NUL 是 ASCII '[=17=]'
。只需将它们称为“0
终止”字符串即可。
所以是的,您应该在 db
的末尾使用 , 0
。
命令行参数始终采用这种 C 字符串格式;这就是 Unix 如何跨系统调用/进程边界传递字符串数据, 以及传递给 ISO C 标准库函数。这包括所有路径名。
在 Linux 中,在进入 _start
时,堆栈指针指向 argc
。上面是 char *argv[]
数组的元素。 (不是 char **argv
指针,只是堆栈上的一个值数组,从 ESP+4 到 ESP+argc*4。也由 NULL 指针 (0
) 终止)。这记录在 i386 和 x86-64 系统 V ABI 文档中。
显示了将 argv[1]
加载到系统调用的 pathname
arg 中的示例。
Reading from a file in assembly 是一个 32 位示例。
这个问题主要是如何在没有 db
或类似的助手的情况下,如何在汇编中处理任意长字符串的路径名。我看过几个例子,例如 this 显示:
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'
但是,我特别想了解如何动态地执行此操作。我想(1)更好地理解文件名在汇编方面的要求(是否需要空终止符等),更重要的是(2)指定文件名 without 使用 db
或任何汇编助手。例如,您可以通过命令行指定文件名,目标文件将不知道其结构。
你是怎么做到的?
只需以某种方式在内存中构建字符串(使用空终止符,正如评论中指出的那样),然后将指针传递给它以代替 file_name
。要使用命令行参数,它已经为您构建,所以只需指向它,如下所示:mov ebx, [esp + 8]
(作为参考,相当于 argv[1]
)。顺便说一句,在实际程序中,您应该在执行此操作之前检查 argc
(位于 [esp]
)以确保它至少为 2.
采用 const char*
且没有长度 arg 的系统调用始终采用 C 字符串:0 终止,隐式长度 。
喜欢open(const char *path, int flags, int mode)
,不喜欢write(int fd, void *buf, size_t len)
。
这就是它们在从 C 调用时起作用的原因,例如 open("input.txt", O_RDONLY)
或 open(argv[1], O_WRONLY|O_CREAT)
。请记住,C 字符串文字为您提供了一个指向静态存储中 char
数组的指针,并带有 0
终止符。
顺便说一句,NULL 是一个指针常量。 NUL 是 ASCII '[=17=]'
。只需将它们称为“0
终止”字符串即可。
所以是的,您应该在 db
的末尾使用 , 0
。
命令行参数始终采用这种 C 字符串格式;这就是 Unix 如何跨系统调用/进程边界传递字符串数据, 以及传递给 ISO C 标准库函数。这包括所有路径名。
在 Linux 中,在进入 _start
时,堆栈指针指向 argc
。上面是 char *argv[]
数组的元素。 (不是 char **argv
指针,只是堆栈上的一个值数组,从 ESP+4 到 ESP+argc*4。也由 NULL 指针 (0
) 终止)。这记录在 i386 和 x86-64 系统 V ABI 文档中。
argv[1]
加载到系统调用的 pathname
arg 中的示例。
Reading from a file in assembly 是一个 32 位示例。