seek_cur 命令将光标设置在文件中的未知位置
seek_cur command sets the cursor in an unknown place in the file
我有一个文件,每行包含一个单词(单词的数量和长度未知),我需要将这些单词重写到另一个文件中,从最后一个单词开始到第一个。当我打印文件中的最后一个词时,我尝试将光标 (seek_cur) 设置为寻找下一个词,但它把它设置在一个未知的地方。尝试打印当前光标以查看会发生什么,它会给出类似“@A”的字符。
第二个 jmp get_out 在写入最后一个词后停止程序,如果它被删除,它会到达 jmp 搜索标签,然后无限地打印相同的最后一个词。
.386
.model flat, stdcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;includem biblioteci, si declaram ce functii vrem sa importam
includelib msvcrt.lib
extern exit: proc
extern fopen: proc
extern fclose: proc
extern fscanf: proc
extern fprintf: proc
extern fseek: proc
extern fgets:proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;declaram simbolul start ca public - de acolo incepe executia
public start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;sectiunile programului, date, respectiv cod
.data
file_read db "r",0
file_write db "w",0
file_name_read db "read.txt",0
file_name_write db "write.txt",0
seek_end dd 2
seek_cur dd 1
seek_set dd 0
caracter_format db "%c",0
string_format db "%s",0
decimal_format db "%d",0
string db 0
caracter db 0
back dd 0
first_word db 0
.code
start:
push offset file_read
push offset file_name_read
call fopen
add esp,8
mov esi,eax
push offset file_write
push offset file_name_write
call fopen
add esp,8
mov edi,eax
;in first_word se pune cuvantul de pe prima linie ca sa fie posibila comparatia mai incolo si sa se iese din bucla cand se ajunge la primul cuvant
repeat_search_first_word:
push offset caracter
push offset caracter_format
push esi
call fscanf
add esp,12
inc back
cmp caracter,0Ah
je out_of_search_first_word
jmp repeat_search_first_word
out_of_search_first_word:
inc back
neg back
push seek_cur
push back
push esi
call fseek
add esp,12
neg back
push esi
push back
push offset first_word
call fgets
add esp,12
mov back,0
;incepe cautarea cuvintelor de la capat
push seek_end
push -1
push esi
call fseek
add esp,12
search:
push offset caracter
push offset caracter_format
push esi
call fscanf
add esp,12
inc back
cmp caracter,0Ah
jne is_caracter
push esi
push back
push offset string
call fgets
add esp,12
push offset string
push offset string_format
push edi
call fprintf
add esp,12
;testam daca cuvantul coincide cu primul (first_word)
mov ebx,0
mov bl,string
cmp bl,first_word
je get_out
add back,2
neg back
;!!!!!!!!!!!!!!
;problema pentru rularea infinita ii aici fiindca seek_cur muta cursorul intr-o zona necunoscuta din fisier
push seek_cur
push back
push esi
call fseek
add esp,12
mov back,0
jmp get_out ;linia 152 lasata fara comentariu permite afisare ultimului cuvant fara sa intre in rularea infinita a buclei
jmp search
is_caracter:
push seek_cur
push -2
push esi
call fseek
add esp,12
jmp search
get_out:
push edi
call fclose
add esp,4
push esi
call fclose
add esp,4
push 0
call exit
end start
read.txt 包含:
abc
defg
hijklm
write.txt 应该是:
hijklm
defg
abc
string db 0
为 1 个字节保留 space(初始化为零)。
然后您调用 fgets(fp, string, back)
,如果它读取超过 1 个字节(包括终止的 0),它将覆盖您数据部分中后面的内容。
在 BSS 中使用更大的缓冲区,例如几 MB 或其他。
使用调试器跟踪函数调用/系统调用。在 Linux 上,您可以使用 ltrace
来跟踪 libc stdio 函数,或 strace
来跟踪它们使用的系统调用。在 Windows IDK 上。您始终可以在每次调用之前单步检查并查看已压入堆栈的参数,以确保它们是正常的,但在查找带有错误参数的参数时,通常更容易看到日志文件样式的列表。
我有一个文件,每行包含一个单词(单词的数量和长度未知),我需要将这些单词重写到另一个文件中,从最后一个单词开始到第一个。当我打印文件中的最后一个词时,我尝试将光标 (seek_cur) 设置为寻找下一个词,但它把它设置在一个未知的地方。尝试打印当前光标以查看会发生什么,它会给出类似“@A”的字符。
第二个 jmp get_out 在写入最后一个词后停止程序,如果它被删除,它会到达 jmp 搜索标签,然后无限地打印相同的最后一个词。
.386
.model flat, stdcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;includem biblioteci, si declaram ce functii vrem sa importam
includelib msvcrt.lib
extern exit: proc
extern fopen: proc
extern fclose: proc
extern fscanf: proc
extern fprintf: proc
extern fseek: proc
extern fgets:proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;declaram simbolul start ca public - de acolo incepe executia
public start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;sectiunile programului, date, respectiv cod
.data
file_read db "r",0
file_write db "w",0
file_name_read db "read.txt",0
file_name_write db "write.txt",0
seek_end dd 2
seek_cur dd 1
seek_set dd 0
caracter_format db "%c",0
string_format db "%s",0
decimal_format db "%d",0
string db 0
caracter db 0
back dd 0
first_word db 0
.code
start:
push offset file_read
push offset file_name_read
call fopen
add esp,8
mov esi,eax
push offset file_write
push offset file_name_write
call fopen
add esp,8
mov edi,eax
;in first_word se pune cuvantul de pe prima linie ca sa fie posibila comparatia mai incolo si sa se iese din bucla cand se ajunge la primul cuvant
repeat_search_first_word:
push offset caracter
push offset caracter_format
push esi
call fscanf
add esp,12
inc back
cmp caracter,0Ah
je out_of_search_first_word
jmp repeat_search_first_word
out_of_search_first_word:
inc back
neg back
push seek_cur
push back
push esi
call fseek
add esp,12
neg back
push esi
push back
push offset first_word
call fgets
add esp,12
mov back,0
;incepe cautarea cuvintelor de la capat
push seek_end
push -1
push esi
call fseek
add esp,12
search:
push offset caracter
push offset caracter_format
push esi
call fscanf
add esp,12
inc back
cmp caracter,0Ah
jne is_caracter
push esi
push back
push offset string
call fgets
add esp,12
push offset string
push offset string_format
push edi
call fprintf
add esp,12
;testam daca cuvantul coincide cu primul (first_word)
mov ebx,0
mov bl,string
cmp bl,first_word
je get_out
add back,2
neg back
;!!!!!!!!!!!!!!
;problema pentru rularea infinita ii aici fiindca seek_cur muta cursorul intr-o zona necunoscuta din fisier
push seek_cur
push back
push esi
call fseek
add esp,12
mov back,0
jmp get_out ;linia 152 lasata fara comentariu permite afisare ultimului cuvant fara sa intre in rularea infinita a buclei
jmp search
is_caracter:
push seek_cur
push -2
push esi
call fseek
add esp,12
jmp search
get_out:
push edi
call fclose
add esp,4
push esi
call fclose
add esp,4
push 0
call exit
end start
read.txt 包含:
abc
defg
hijklm
write.txt 应该是:
hijklm
defg
abc
string db 0
为 1 个字节保留 space(初始化为零)。
然后您调用 fgets(fp, string, back)
,如果它读取超过 1 个字节(包括终止的 0),它将覆盖您数据部分中后面的内容。
在 BSS 中使用更大的缓冲区,例如几 MB 或其他。
使用调试器跟踪函数调用/系统调用。在 Linux 上,您可以使用 ltrace
来跟踪 libc stdio 函数,或 strace
来跟踪它们使用的系统调用。在 Windows IDK 上。您始终可以在每次调用之前单步检查并查看已压入堆栈的参数,以确保它们是正常的,但在查找带有错误参数的参数时,通常更容易看到日志文件样式的列表。