You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编(ASM)中如何判断文件时长?任务场景与代码求助

问题描述

我正在完成一个任务:用GetOpenFileName选择文件,判断文件是否创建时间小于3天,若是则读取文件内容;否则弹出对话框询问是否删除,用户确认就删除。要求用到的结构要放在动态分配的内存中。

目前已经实现了文件打开功能,但不知道怎么判断文件时长。我初步想的是用GetFileTime获取文件时间,转成本地时间再转成系统时间,之后做减法判断,但具体操作不清楚,也想知道有没有替代方法。

现有代码

File.inc

include WINDOWS.inc

include user32.inc
include kernel32.inc
include comdlg32.inc

includelib user32.lib
includelib kernel32.lib
includelib comdlg32.lib

.data

    Time_title  db ' Lab_3',0
    format db 'More than 3 days. Delete file?', 0
    buf db 255 dup(0)   
    hFile dd 0
    readed dd 0
    hmem dd 0

File.asm

.386
.model flat,STDCALL
option casemap :none  ;区分大小写
include Third.inc
include RADbg.inc

Mem_Alloc PROC Buf_Size:DWORD
    add Buf_Size,4  
    invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,Buf_Size
    push eax 
    invoke GlobalLock,eax 
    pop [eax]
    add eax,4
Mem_Alloc endp


Mem_Free PROC DATA:DWORD
    mov eax,DATA
    sub eax,4   
    mov eax,[eax]   
    push eax        
    push eax
    call GlobalUnlock   
    call GlobalFree 
Mem_Free endp


.code
Begin:
    call main
    invoke ExitProcess,NULL

main proc
    LOCAL ftCreate, ftLocale: FILETIME;
    LOCAL stUTC, stLocal: SYSTEMTIME;

    invoke Mem_Alloc, 1000h
    mov hmem, eax
    invoke Mem_Alloc, sizeof OPENFILENAME
    mov edi, eax
    assume edi: ptr OPENFILENAME
    xor eax, eax
    mov [edi].lStructSize, sizeof OPENFILENAME
    mov [edi].lpstrFile, offset buf
    mov [edi].nMaxFile, 255
    invoke GetOpenFileName, edi
    invoke CreateFile, [edi].lpstrFile, GENERIC_READ,\
        FILE_SHARE_READ, NULL, OPEN_EXISTING,\
        FILE_ATTRIBUTE_NORMAL, NULL
    mov hFile,eax           ;保存文件句柄
    invoke GetFileTime, hFile, addr ftCreate, NULL, NULL
    invoke FileTimeToLocalFileTime, addr ftCreate, addr ftLocale
    invoke FileTimeToSystemTime, addr ftCreate, addr stUTC

    cmp eax, 1
    jz l1
    invoke ReadFile, hFile, hmem, 1000h, addr readed, 0
    invoke MessageBox, 0, hmem, addr Time_title, MB_OKCANCEL

    jmp l2

l1:
    invoke MessageBox, 0, addr format, addr Time_title, MB_OKCANCEL
    cmp eax, IDOK
    jne l2
    invoke DeleteFile, addr [edi].lpstrFile

l2:

    assume edi: dword
    invoke CloseHandle, hFile
    invoke Mem_Free, hmem
    invoke Mem_Free, edi

    ret

main endp   
end Begin

解决方法

方法1:直接计算FILETIME时间差(推荐)

FILETIME结构存储的是自1601年1月1日以来的100纳秒数,所以可以直接计算当前时间和文件创建时间的差值,判断是否超过3天的总纳秒数。

3天的总100纳秒数计算:3天 = 32460*60秒 = 259200秒,乘以107(因为1秒=107个100纳秒),得到2592000000000。

修改main proc中的代码,添加获取当前系统时间并转成FILETIME的步骤:

main proc
    LOCAL ftCreate, ftNow, ftDiff: FILETIME;
    LOCAL stNow: SYSTEMTIME;

    ; ... 保留原有文件选择、打开代码 ...

    invoke GetFileTime, hFile, addr ftCreate, NULL, NULL
    ; 获取当前系统时间并转成FILETIME
    invoke GetLocalTime, addr stNow
    invoke SystemTimeToFileTime, addr stNow, addr ftNow

    ; 计算时间差:当前时间 - 文件创建时间
    mov eax, ftNow.dwLowDateTime
    sub eax, ftCreate.dwLowDateTime
    mov ftDiff.dwLowDateTime, eax
    mov eax, ftNow.dwHighDateTime
    sbb eax, ftCreate.dwHighDateTime
    mov ftDiff.dwHighDateTime, eax

    ; 判断时间差是否超过3天(2592000000000个100纳秒)
    mov eax, ftDiff.dwHighDateTime
    cmp eax, 00000000h  ; 高32位如果大于0,肯定超过3天
    jg l1
    mov eax, ftDiff.dwLowDateTime
    cmp eax, 2592000000000h
    jge l1

    ; 文件创建时间小于3天,执行读取逻辑
    invoke ReadFile, hFile, hmem, 1000h, addr readed, 0
    invoke MessageBox, 0, hmem, addr Time_title, MB_OKCANCEL
    jmp l2

l1:
    ; 文件超过3天,询问删除
    invoke MessageBox, 0, addr format, addr Time_title, MB_OKCANCEL
    cmp eax, IDOK
    jne l2
    invoke DeleteFile, addr [edi].lpstrFile

l2:
    ; ... 保留原有资源释放代码 ...
    ret
main endp

方法2:通过SYSTEMTIME计算日期差

如果一定要用SYSTEMTIME进行日期计算,需要把文件创建时间和当前时间转成SYSTEMTIME后,手动计算日期差值:

main proc
    LOCAL ftCreate, ftLocale: FILETIME;
    LOCAL stFile, stNow: SYSTEMTIME;

    ; ... 保留原有文件选择、打开代码 ...

    invoke GetFileTime, hFile, addr ftCreate, NULL, NULL
    invoke FileTimeToLocalFileTime, addr ftCreate, addr ftLocale
    invoke FileTimeToSystemTime, addr ftLocale, addr stFile
    invoke GetLocalTime, addr stNow

    ; 计算日期差:当前日期 - 文件创建日期
    mov eax, stNow.wYear
    sub eax, stFile.wYear
    mov ecx, eax
    imul ecx, 365
    mov eax, stNow.wMonth
    sub eax, stFile.wMonth
    imul eax, 30  ; 简化计算,忽略月份天数差异
    add ecx, eax
    mov eax, stNow.wDay
    sub eax, stFile.wDay
    add ecx, eax

    ; 判断是否超过3天
    cmp ecx, 3
    jge l1

    ; 读取文件逻辑
    invoke ReadFile, hFile, hmem, 1000h, addr readed, 0
    invoke MessageBox, 0, hmem, addr Time_title, MB_OKCANCEL
    jmp l2

l1:
    ; 删除询问逻辑
    invoke MessageBox, 0, addr format, addr Time_title, MB_OKCANCEL
    cmp eax, IDOK
    jne l2
    invoke DeleteFile, addr [edi].lpstrFile

l2:
    ; ... 保留原有资源释放代码 ...
    ret
main endp

注意:这种方法是简化计算,没有考虑闰年、不同月份天数不同的情况,精度不如FILETIME直接计算。

内容的提问来源于stack exchange,提问作者Sollpix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:40:22