【发布时间】:2011-11-19 13:48:21
【问题描述】:
我正在努力学习汇编,如果我的问题是初级的,请多多包涵
以下代码扫描一个目录并打印出其中的所有文件和目录,除了以点开头的文件和目录。它似乎工作正常。
但是,一旦我取消注释 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”下面的目录,导致它列出了那里的文件和“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
【问题讨论】: