【问题标题】:How to read from and write to files using NASM for x86-64bit如何使用 NASM for x86-64bit 读取和写入文件
【发布时间】:2013-12-06 16:11:08
【问题描述】:

我有一个适用于标准 I/O 设备的 64 位 Linux 系统的 NASM 程序,它看起来像这样:

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

我需要程序来读取和写入文件,但我找不到必须使用哪些系统调用以及如何使用它们来实现这些结果的任何地方。所以,我想知道你们中是否有人可以帮助我。提前致谢。

【问题讨论】:

    标签: linux assembly x86-64 nasm system-calls


    【解决方案1】:

    使用系统调用“open”和“close”:

    在 64 位 Linux 下打开文件:

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

    关闭文件:

    rax = 3
    rdi = file handle
    syscall
    

    读取/写入文件:

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

    【讨论】:

      【解决方案2】:

      ;这个程序只是覆盖result.txt

      ;要写在底部,你需要lseek到最后

      节.数据

      prompt db "输入你的文本:",10

      length equ $ - 提示

      文本乘以 255 db 0

      文本大小等于 $-text

      fname db "result.txt",0

      fd dq 0

      狐狸 dq 0

      全局_start

      部分.文本

      _开始:

      mov al,1

      mov dil,al

      mov esi,提示

      mov dl,长度

      系统调用

      mov al,0

      mov dil,al

      mov rsi,文本

      mov rdx,文本大小

      系统调用

      mov [thefox],rax

      mov rax,2

      mov rdi,fname

      mov rsi,0102o

      mov rdx,0666o

      系统调用

      mov [fd],rax

      mov rdx,[thefox]

      mov rsi,文本

      mov rdi,[fd]

      mov rax,1

      系统调用

      mov rdi,[fd]

      mov rax,3

      系统调用

      mov rax,60

      系统调用

      【讨论】:

      • mov al,1 - 假设 RAX=0 开始,只有当 Linux 启动 静态 链接的可执行文件时才会发生这种情况。 (为了避免信息泄漏;即使 ABI 实际上也不能保证)。如果您使用此代码创建了一个动态链接的可执行文件,那么在首先从/lib64/ld-linux-x86-64.so.2 运行代码之后,一旦执行到达您的_start,所有寄存器(堆栈指针除外)都将具有非零垃圾。这不是codegolf.stackexchange.com,所以不要费心试图通过利用 Linux 静态可执行寄存器初始化状态来节省几个字节,
      • 当您使用 mov rax,3 而不是 mov eax,3 并使用 64 位操作数大小作为文件描述符时,您将击败您的 mov al,1 代码高尔夫球。 Unix fdint,32 位又名 dword。它也不需要保存到内存中,只需将其保存在寄存器中即可。此外,使用default rel 使mov rdx,[thefox] 之类的东西使用更高效、更紧凑的RIP 相对寻址。
      • 另一个错误:thefox dw 0 仅保留 2 个字节,但您使用 mov rdx,[thefox] 从其中加载 6 个字节,而不是 movzx。您只存储来自 read 返回值的 2 个字节。 (假设第一个 write 没有返回错误,那么您的系统调用号将是 0xffffff00 并且它会返回 -EINVAL 因为您在第一个系统调用之后使用了 mov al,0。)无论如何,如果有人试图构建这段代码,然后在.data 中添加其他非零内容,加载到RDX 中,因为长度会返回垃圾。同样,显而易见的解决方案是将长度保存在另一个寄存器中。
      • 如果您看到我的代码以 exit syscall (rax=60) 结尾。那是纯 asm 那是静态可执行文件。我的代码已经编译并且没有错误。但是,如果您与 dinamic exec 合作,那将是错误的。我希望这可以解释它是如何工作的,并且已经编译并运行没有错误。如果你像我一样做就没有错误,因为我已经运行它了。
      • 堆栈溢出答案中的代码通常应该是可用的,作为更大程序的一部分。此代码并非如此,它仅适用于静态可执行文件的_start。如果您想以这种方式优化代码大小,则应使用 cmets 记录任何所需的前置条件(如归零寄存器)。是的,如果您阅读我的第一条评论,应该清楚我完全理解为什么这在静态可执行文件中有效。我投了反对票,因为它不是如何编写代码的一个很好的例子,并且有多个错误(比如从 dw 0 加载 8 个字节),这些错误只会在这里工作。
      猜你喜欢
      • 1970-01-01
      • 2012-09-15
      • 2015-07-26
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      • 2010-11-11
      相关资源
      最近更新 更多