我有以下程序。它用于检查文件名是否表示目录,如果是目录则设置Carry标志,否则清除它。
现在它适用于我测试过的文件和目录,但我怀疑这只是巧合,因为我找不到有关stat()函数的任何有用文档,所以我不得不猜测。
我需要知道的是结构中的哪个偏移量我可以找到该文件是否是目录,以及哪个值意味着什么。从我的测试中我发现我的所有测试文件在偏移20时的值为1,而目录有2或3,但这可能只是巧合,我不知道偏移20的值实际上代表什么。可以是任何东西,或者什么也不是。
另外,我为结构预留了100个字节,但我怀疑这可能是太多的内存。再一次,我真的可以使用一些与汇编而不是C相关的文档。关于C的所有内容都是关于C的,我能做的最好的就是做出猜测。
...
[SECTION .bss]
StatBuf resb 100
...
isdir:
pushad
push StatBuf
push eax ; Filename passed in eax
call stat
add esp, 8
cmp eax, 0 ; stat returns 0 on success
jne .error ; -1 (not 0) on failure
mov eax, StatBuf ; Stats stored in StatBuf
cmp byte [eax+20], 1 ; Guess: All files have value 1 at offset 20?
jne .yes ; Guess: Dirs either 2 or 3?
clc ; Not a directory
jmp .done
.yes:
stc ; File is a directory
jmp .done
.error:
clc ; Error, not a directory
jmp .done
.done:
popad
ret
更新0
我现在做以下事情,并且它似乎再次起作用,但我不确定它是否真的正确。 ebx
之后and
中的值对于文件看起来是0而对于目录看起来是64,不应该是相反的方式(目录为0)?
mov eax, StatBuf
mov ebx, dword [eax+17]
and ebx, 0x40
cmp ebx, 0
jne .yes
答案 0 :(得分:1)
您要查看S_IFDIR
in the st_mode
member。这是第三个成员,应该是[16]
和[23]
rd字节之间的单个位值(它被定义为掩码)。我会提供更多信息,但我现在正在使用Windoze盒子。
#include <sys/stat.h>
#include <stdio.h>
#include <stddef.h>
main() {
printf("st_mode offset = %zu\n", offsetof(struct stat, st_mode));
printf("S_IFDIR mask = %x\n", S_IFDIR);
}
执行给了我:
matt@stanley:~$ gcc -o mask /home/matt/Desktop/mask.c
matt@stanley:~$ ./mask
st_mode offset = 24
S_IFDIR mask = 4000
由于机器是小端,这告诉我们如果设置了第25个字节的第2个最高有效位,它就是一个目录。在汇编中,您应该使用[eax+25]
读取此字节and
,0x40
,然后将其与零进行比较。
或者你可以学习C。
以上是在x86_64 OS上执行的。 x86上的位置会有所不同。
ebx
之后and ebx 0x40
的值如果是目录则不为零。
再次,如果你使用C,你不必担心你的平台是什么。但是,如果您为32位操作系统编译程序,如果该操作系统支持32位二进制文件,它仍将在64位操作系统下正确运行。如果你在集会中这样做,我会选择这条路线。