Я пытаюсь изучить ассемблер, поэтому терпите меня, если мои проблемы элементарные
Следующий код сканирует каталог и распечатывает все файлы и каталоги в нем, кроме тех, которые начинаются с точки.Кажется, он работает нормально.
Однако, когда я раскомментирую строку call scandir
, чтобы включить рекурсию, она выводит длинный список повторяющихся имен файлов (подробности см. Ниже).
Кроме того, я хотел бы проверить, является ли файл каталогом или нет.Как бы я это сделал?Насколько я могу судить, пока это не проблема, поскольку, если это не каталог, вызов scandir просто вернется без каких-либо действий, но проверка может стать важной позже (и, кажется, это хорошо сделатьв любом случае).
[SECTION .data]
DirName db 'test', 0
[SECTION .bss]
[SECTION .text]
extern puts ; Externals from glibc standard C library
extern opendir ; Externals from dirent.h
extern closedir
extern readdir
global main
scandir:
pushad ; Save caller's registers
push eax ; Directory is passed in eax
call opendir ; Open directory
add esp, 4
cmp eax, 0 ; opendir returns 0 on failure
je .done
mov ebx, eax ; Move directory handle to ebx
.read:
push ebx ; Push directory handle
call readdir ; Read a file from directory
add esp, 4 ; Clean up the stack
cmp eax, 0 ; readdir returns 0 on failure or when done
je .close
add eax, 11 ; File name is offset at 11 bytes
mov cl, byte [eax] ; Get first char of filename
cmp cl, 46 ; Ignore files and dirs which begin with a dot
je .read ; (., .., and hidden files)
;call scandir ; Call scandir recursively
; If file is not a dir opendir will simply fail
push eax
call puts
add esp, 4
jmp .read
.close:
push ebx ; Close directory
call closedir
add esp, 4
jmp .done
.done:
popad ; Restore caller's registers
ret
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx ; Must preserve ebp, ebx, esi and edi
push esi
push edi
; start
mov eax, DirName
call scandir
; end
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp, ebp ; Destroy stack frame
pop ebp
ret
Структура каталога тестового каталога выглядит следующим образом:
bar [directory]
bas.c
test1.c
test2.c
test3.c
foo.txt
test
Без рекурсии она распечатывает файлы в тестовом каталоге, как и должно, но с рекурсиейкажется, что он печатает следующее:
test1.c
bar
test3.c
[repeat 3 lines ~1000 times]
test
foo.txt
test2.c
[repeat 3 lines ~1000 times]
Редактировать: Теперь это, в основном, работает, я думаю, за исключением того, что изначально оно кажется обратно в каталог ниже 'test', вызывая егоперечислить файлы там и файлы в 'тесте' дважды
[SECTION .data]
ParentDir db '..', 0
CurrentDir db '.', 0
DirName db 'test', 0
[SECTION .bss]
[SECTION .text]
extern puts ; Externals from glibc standard C library
extern opendir ; Externals from dirent.h
extern closedir
extern readdir
extern chdir
global main
scandir:
pushad ; Save caller's registers
push eax ; Directory is passed in eax
call opendir ; Open directory
add esp, 4
cmp eax, 0 ; opendir returns 0 on failure
je .done
mov ebx, eax ; Move directory handle to ebx
.read:
push ebx ; Push directory handle
call readdir ; Read a file from directory
add esp, 4 ; Clean up the stack
cmp eax, 0 ; readdir returns 0 on failure or when done
je .close
add eax, 11 ; File name is offset at 11 bytes
mov cl, byte [eax] ; Get first char of filename
cmp cl, 46 ; Ignore files and dirs which begin with a dot
je .read ; (., .., and hidden files)
cmp byte [eax-1], 4
jne .notdir
push eax
call chdir
add esp, 4
mov eax, CurrentDir
call scandir ; Call scandir recursively
jmp .read
.notdir:
push eax
call puts
add esp, 4
jmp .read
.close:
push ebx ; Close directory
call closedir
add esp, 4
push ParentDir
call chdir
add esp, 4
jmp .done
.done:
popad ; Restore caller's registers
ret
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx ; Must preserve ebp, ebx, esi and edi
push esi
push edi
; start
mov eax, DirName
call scandir
; end
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp, ebp ; Destroy stack frame
pop ebp
ret