Nasm x86_64:为什么我不能写入和读取同一个文件?



我在 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 来找到它,但我无法弄清楚如何调用它。

弗特尔

由于文件是按顺序读取的,因此在追加模式下调用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

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

最新更新