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

汇编实现凯撒密码时写入超512字节文件失败的问题排查

凯撒密码文件加解密程序问题修复:仅处理前512字节

问题描述

我用汇编实现了凯撒密码程序,支持文件加解密、密码分析,要求按512字节块读写文件,但处理超过512字节的文件时,仅能输出前512字节内容。曾怀疑问题出在WriteFile调用,但排查后发现根源并非该函数本身。

错误根源:寄存器冲突

核心问题是寄存器被意外覆盖:
在descriptografar和criptografar函数中,你将输入文件的句柄存入了edi寄存器,但在后续处理缓冲区的循环里,执行了lea edi, [buffer],直接覆盖了edi中保存的文件句柄。当第一次循环结束后,第二次调用ReadFile时,edi已经指向缓冲区而非文件句柄,导致无法读取后续文件块,最终只处理了第一块512字节数据。

修复方案

更换用于保存文件句柄的寄存器,避免和缓冲区操作使用的寄存器冲突。比如将输入文件句柄存入ebp(或其他未被缓冲区操作占用的寄存器),保留edi用于缓冲区指针操作。

修正后的核心代码片段(以descriptografar为例)

descriptografar:
    ; ... 省略原有输入读取、密钥转换代码 ...

    invoke CreateFile, addr inputFileBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
    mov ebp, eax  ; 用ebp保存输入文件句柄,替换原来的edi

    invoke CreateFile, addr outputFileBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
    mov ebx, eax

    @@readLoop1:
        invoke ReadFile, ebp, addr buffer, sizeof buffer, addr bytesRead, NULL  ; 这里用ebp作为文件句柄
        xor ecx, ecx
        mov ecx, dword ptr [bytesRead]
        cmp ecx, 0
        je @@endReadLoop1

        lea edi, [buffer]
        mov esi, edi
        mov edx, ecx

        @@loop1:
            mov al, byte ptr [esi]
            sub al, byte ptr [keyBuffer]
            mov byte ptr [edi], al

            inc esi
            inc edi
            dec edx
            jnz @@loop1

        mov ecx, dword ptr [bytesRead]
        invoke WriteFile, ebx, addr buffer, ecx, addr bytesWritten, NULL

        jmp @@readLoop1
    @@endReadLoop1:
    invoke CloseHandle, ebp  ; 关闭文件句柄时用ebp
    invoke CloseHandle, ebx

    jmp menuLoop

同样需要修正criptografar函数

将其中保存输入文件句柄的edi替换为ebp,对应ReadFile和CloseHandle的调用也改为使用ebp:

criptografar:
    ; ... 省略原有输入读取、密钥转换代码 ...

    invoke CreateFile, addr inputFileBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
    mov ebp, eax  ; 替换edi为ebp

    invoke CreateFile, addr outputFileBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
    mov ebx, eax

    @@readLoop2:
        invoke ReadFile, ebp, addr buffer, sizeof buffer, addr bytesRead, NULL  ; 使用ebp
        xor ecx, ecx
        mov ecx, dword ptr [bytesRead]
        cmp ecx, 0
        je @@endReadLoop2

        lea edi, [buffer]
        mov esi, edi
        mov edx, ecx

        @@loop2:
            mov al, byte ptr [esi]
            add al, byte ptr [keyBuffer]
            mov byte ptr [edi], al

            inc esi
            inc edi
            dec edx
            jnz @@loop2

        mov ecx, dword ptr [bytesRead]
        invoke WriteFile, ebx, addr buffer, ecx, addr bytesWritten, NULL        

        jmp @@readLoop2
    @@endReadLoop2:

    invoke CloseHandle, ebp  ; 使用ebp关闭句柄
    invoke CloseHandle, ebx

    jmp menuLoop

额外注意事项

  • 凯撒密码仅对字母有效,当前代码会修改所有字节(包括非字母字符),如果需要仅处理字母,需添加判断逻辑(比如检查ASCII范围是否在A-Z或a-z之间)。
  • 密钥处理部分,atodw返回的是双字,但你只取了al(字节),如果密钥超过255会被截断,但需求里密钥是1-20,所以当前逻辑没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:22:06