我必须编写一个程序,该程序逐个字符地读取给定文本文件并对其执行某些操作。
首先,我想打印每个字符并在到达文件末尾时停止。这两件事都不起作用。在较旧的程序中,我使用 rax 来检测何时到达文件末尾,但这在该程序中不起作用。 我还有一个问题,当我一次读入 char 时,程序会在每个字符之间打印一个点。当我一次读取多个字符时,不会出现此问题。
文件:Arcu scelerisque aliquam。 Nullam viverra magna vitae leo。 (...)
控制台:$ ./wortzaehl
输出:A.r.c.u. .s.c.e.l.e.
这是我当前的代码: (我使用了r9,因为我无法检测到文件结尾) (我知道这段代码可能效率很低)
%define STDOUT 1
%define STDIN 0
%define READONLY 0
%define SYS_READ 0
%define SYS_WRITE 1
%define SYS_OPEN 2
%define SYS_CLOSE 3
%define SYS_EXIT 60
section .data
newline:
db 0x0a
space:
db 0x20
tab:
db 0x09
invalid_argument_text:
db "No Path given"
section .bss
input_buffer:
resb 1
section .text
global _start
;;;================= Read/Write Functions =============================
write_invalid_arg:
;; save registers that are used in the code
push rax
push rdi
push rdx
mov rax, SYS_WRITE
mov rdi, STDOUT
mov rsi, invalid_argument_text
mov rdx, 13
call make_syscall
pop rdx
pop rdi
pop rax
jmp finish
write_newline:
;; save registers that are used in the code
push rax
push rdi
push rsi
push rdx
;; prepare arguments for write syscall
mov rax, SYS_WRITE ; write syscall
mov rdi, STDOUT ; fd = 1 (stdout)
mov rsi, newline ; string
mov rdx, 1 ; length
call make_syscall
;; restore registers (in opposite order)
pop rdx
pop rsi
pop rdi
pop rax
ret
write_char:
push rsi ; speicher rsi
mov rax, SYS_WRITE ; Syscall Typ
mov rdi, STDOUT ; Out
mov rsi, input_buffer ; Aktuelle Zeile
mov rdx, 1 ; Laenge der Zeile
call make_syscall ; syscall
pop rsi ; Hol rsi zurueck
ret
open_file:
push rdi
push rsi
push rdx
mov rax, SYS_OPEN ; Datei oeffnen
mov rdi, rsi ; Pfad zur Datei
mov rsi, READONLY ; Nur lesen
call make_syscall
mov r11, rax
pop rdx
pop rsi
pop rdi
ret
read_char:
push rdi
push rsi
push rdx
mov rdi, r11 ; Geoeffnete Datei
mov rax, SYS_READ
mov rsi, input_buffer
mov rdx, 1
call make_syscall
pop rdx
pop rsi
pop rdi
make_syscall:
push rcx ; clobbered by syscall
push r11 ; clobbered by syscall
syscall ; system call
pop r11
pop rcx
ret
; ======================================================
count_text:
mov r8, 0 ; Zeichen
mov r9, 0 ; Worte
mov r10, 0 ; Zeilen
call open_file
next_char:
call read_char
cmp r8, 10
je text_finished
;cmp rax, 0
;jne text_finished
;call write_invalid_arg
call write_char
inc r8
jmp next_char
text_finished:
; Text schliessen
mov rax, SYS_CLOSE
mov rdi, r10
call make_syscall
ret
;========================
_start:
pop rbx ; argc (>= 1 guaranteed) Anzahl Args
dec rbx ; remove command
jz write_invalid_arg ; when no arg after command
pop rsi ; remove letters of command
pop rsi ; Pfad
call count_text
finish:
call write_newline
;; exit program via syscall exit (necessary!)
mov rax, SYS_EXIT ; exit syscall
mov rdi, 0 ; exit code 0 (= "ok")
syscall ; kernel interrupt: system call
我做了一些测试,我认为输入缓冲区不仅包含读取的字符。当我执行以下操作时:
mov r15b, byte [input_buffer]
mov rsi, r15 ; Aktuelle Zeile
唯一的输出是点
编辑:我忘记了 read_char 中的返回。现在唯一的问题是文件末尾的检测
我有两个问题:
这两个问题都被一个错误解决了:我忘记了 read_char 中的“ret”。
与
cmp rax, 0
jne text_finished
我现在可以检测是否到达文件末尾。