linux - 纳斯姆 x86_64 : Why can't I write and read from the same file?

标签 linux assembly x86-64 nasm system-calls

我在 Nasm x86_64 中处理文件时遇到问题。 我已经正确打开了文件,我可以写入文件或从中读取内容,但是如果我在写入内容后尝试从文件中读取内容,我什么也得不到。 所以我从文件中读取或写入。 奇怪的是,如果我第一次读写,我没有任何问题,一切正常,所以问题只出现在我第一次写入然后读取时。 有人可以帮我解决这个问题并找出原因吗?

这是打开文件的代码:

    mov     rax, SYS_OPEN
    mov     rdi, filename
    mov     rsi, O_CREAT+O_RDWR+O_APPEND
    mov     rdx, 0744o
    syscall
    push    rax

关闭文件的代码:

    mov     rax, SYS_CLOSE
    mov     rdi, r11
    syscall

打印字符串的代码:

    mov rdx, rax
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, temp
    syscall

getLength的代码(参数是我要获取长度的字符串):

%macro getLength 1
    mov     r10, %1
    mov     r11, r10

    %%begin:
        cmp     byte [r11], 10
        je      %%end
        inc     r11
        jmp     %%begin

    %%end:
        sub     r11, r10
%endmacro

要编写的代码:

    getLength msg
    mov     rax, SYS_WRITE
    mov     rdi, [rsp]
    mov     rsi, msg
    mov     rdx, r11
    syscall

要阅读的代码:

    mov     rax, SYS_READ
    mov     rdi, [rsp]
    mov     rsi, temp    ;buffer to store the string read
    mov     rdx, 10
    syscall

读取的代码和写入的代码都可以单独完美地工作,问题是当我在编写代码之后使用读取的代码时。

所以这段代码可以工作。

    %include "./standardlib.inc"

section .data
    filename db "./file.txt", 0
    msg     db "hello", 10

section .bss
    temp    resb 10

section .text
    global _start:

    _start:
    mov     rax, SYS_OPEN
    mov     rdi, filename
    mov     rsi, O_CREAT+O_RDWR+O_APPEND
    mov     rdx, 0744o
    syscall
    push    rax

    mov     rax, SYS_READ
    mov     rdi, [rsp]
    mov     rsi, temp
    mov     rdx, 10
    syscall

    mov rdx, rax
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, temp
    syscall

    getLength msg

    mov     rax, SYS_WRITE
    mov     rdi, [rsp]
    mov     rsi, msg
    mov     rdx, r11
    syscall

    mov     rax, SYS_CLOSE
    mov     rdi, r11
    syscall

    exit

这个 coe 不起作用:

    %include "./standardlib.inc"

section .data
    filename db "./file.txt", 0
    msg     db "hello", 10

section .bss
    temp    resb 10

section .text
    global _start:

    _start:
    mov     rax, SYS_OPEN
    mov     rdi, filename
    mov     rsi, O_CREAT+O_RDWR+O_APPEND
    mov     rdx, 0744o
    syscall
    push    rax

    getLength msg

    mov     rax, SYS_WRITE
    mov     rdi, [rsp]
    mov     rsi, msg
    mov     rdx, r11
    syscall

    mov     rax, SYS_READ
    mov     rdi, [rsp]
    mov     rsi, temp
    mov     rdx, 10
    syscall

    mov rdx, rax
    mov rax, SYS_WRITE
    mov rdi, STDOUT
    mov rsi, temp
    syscall

    mov     rax, SYS_CLOSE
    mov     rdi, r11
    syscall

    exit

所以我明白我必须使用 lseek 返回到文件的开头。 这是 sys_lseek 的一个好的调用吗?

    mov rax, 8        ;sys_lseek syscall ID
    mov rdi, [rsp]    ;file descriptor
    mov rsi, 0        ;The offset
    mov rdx, 0        ;I imagine the value of SEEK_SET

sys_lseek

我认为偏移值是错误的,我应该使用ftell来找到它,但我不知道如何调用它。

ftell

最佳答案

由于文件是按顺序读取的,因此在追加模式下调用 sys_read 后,光标会移动到文件末尾,因此如果您尝试从该位置读取,您将不会读取任何内容。

要解决此问题,您必须将光标重新定位到文件的开头。

为此,您可以使用 lseek 系统调用。

    mov     rax, 8        ;system call Id for sys_lseek
    mov     rdi, [rsp]    ;file descriptor
    mov     rsi, 0        ;offset value, so number of characters to move the cursor
    mov     rdx, 0        ;It indicates the initial position from which move the cursor, in this case the value 0 indicates that the initial position is the beginning of the file
    syscall

调用此系统调用后,光标位置将位于文件的开头,您将能够从中读取内容。

关于linux - 纳斯姆 x86_64 : Why can't I write and read from the same file?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57836090/

相关文章:

ruby - 停止 kill 命令

c - 为什么编译的 C 程序依赖于操作系统

ubuntu - 如何在 Ubuntu i686 架构中安装 .NET Core 2.0?

c - 使用内联汇编时出现段错误(核心转储)错误

windows - NASM ReadConsoleA 或 WriteConsoleA 缓冲区调试问题

java - 我已经使用 maven 构建了一个 jar 文件,但无法在 linux 中使用 "java"命令执行它

linux - 如何在 Perl 中确定文件

assembly - 所有数据都是有效的 x86 16 位机器代码吗?

assembly - 将 Go 链接到任意目标文件(程序集)?

c - 提高寄存器机虚拟机上循环的简单自制 JIT 的性能