assembly 我如何用汇编语言修复我的Caesar Cipher实现以读取多位密钥?

qeeaahzv  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(120)

我的代码实现了Caesar Cipher,它向用户询问输入文件的名称,其中包含我要加密/解密的字符串,输出文件的名称和密钥/密码,我的问题是它只阅读密钥的第一个数字,如果我给予它一个有两位数的数字作为密钥,那么它只读取第一个,如14,15,它只读取1。我该怎么解决这个问题?下面是代码:

.686
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib

.data
    ; Strings do menu e prompts
    menuTitle       db "Cifra de Cesar",13,10,0
    option1         db "1. Descriptografar",13,10
    option2         db "2. Criptografar",13,10
    option3         db "3. Criptoanalise",13,10
    option4         db "4. Sair",13,10
    menuPrompt      db "Escolha uma opcao:",0

    filePrompt      db "Digite o nome do arquivo de entrada:",0
    outFilePrompt   db "Digite o nome do arquivo de saida:",0
    keyPrompt       db "Digite a chave (1 a 20):",0
    
    ; Buffers e variáveis auxiliares
    inputFileBuffer  db 10240 dup(0)
    outputFileBuffer db 10240 dup(0)
    outputBuffer    db 10240 dup(0)
    userInputBuffer db 256 dup(0)
    buffer          db 512 dup(0)
    keyBuffer       db 256 dup(0)
    console_count   dd 0
    inputHandle     dd 0
    outputHandle    dd 0
    bytesRead       dd 0
    bytesWritten    dd 0    

.code
start:
    ; Obtém os handles de entrada e saída padrão
    invoke GetStdHandle, STD_INPUT_HANDLE
    mov inputHandle, eax

    invoke GetStdHandle, STD_OUTPUT_HANDLE
    mov outputHandle, eax
    

menuLoop:
    ; Exibe o menu de opções e lê a escolha do usuário
    invoke WriteConsole, outputHandle, addr menuTitle, sizeof menuTitle, addr console_count, NULL
    invoke WriteConsole, outputHandle, addr option1, sizeof option1, addr console_count, NULL
    invoke WriteConsole, outputHandle, addr option2, sizeof option2, addr console_count, NULL
    invoke WriteConsole, outputHandle, addr option3, sizeof option3, addr console_count, NULL
    invoke WriteConsole, outputHandle, addr option4, sizeof option4, addr console_count, NULL
    invoke WriteConsole, outputHandle, addr menuPrompt, sizeof menuPrompt, addr console_count, NULL
    invoke ReadConsole, inputHandle, addr userInputBuffer, sizeof userInputBuffer, addr console_count, NULL

    ; Verifica a opção escolhida e executa a ação correspondente
    mov al, byte ptr [userInputBuffer]
    cmp al, '4'
    je exitProgram

    cmp al, '1'
    je descriptografar
    cmp al, '2'
    je criptografar
    cmp al, '3'
    je criptoanalise

    jmp menuLoop

descriptografar:
    ; Solicita e lê os nomes dos arquivos de entrada, saída e chave
    invoke StdOut, addr filePrompt
    invoke StdIn, addr inputFileBuffer, 10240

    invoke StdOut, addr outFilePrompt
    invoke StdIn, addr outputFileBuffer, 10240

    invoke StdOut, addr keyPrompt
    invoke StdIn, addr keyBuffer, 256

    invoke atodw, addr keyBuffer
    mov ecx, eax

    invoke CreateFile, addr inputFileBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
    mov edi, eax

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

    invoke ReadFile, edi, addr buffer, sizeof buffer, addr bytesRead, NULL
    

    xor ecx, ecx
    mov cl, byte ptr [bytesRead]

    lea edi, [buffer]
    mov esi, edi

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

        inc esi
        inc edi

        loop @@loop1

    ; Atualize o valor de ecx para o número correto de bytes lidos
    mov ecx, [bytesRead]

    invoke WriteFile, ebx, addr buffer, ecx, addr bytesWritten, NULL

    invoke CloseHandle, edi
    invoke CloseHandle, ebx

    jmp menuLoop

criptografar:
    invoke StdOut, addr filePrompt
    invoke StdIn, addr inputFileBuffer, 10240

    invoke StdOut, addr outFilePrompt
    invoke StdIn, addr outputFileBuffer, 10240

    invoke StdOut, addr keyPrompt
    invoke StdIn, addr keyBuffer, 256

    invoke atodw, addr keyBuffer
    mov ecx, eax

    invoke CreateFile, addr inputFileBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL

    mov edi, eax

    invoke CreateFile, addr outputFileBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL

    mov ebx, eax

    invoke ReadFile, edi, addr buffer, sizeof buffer, addr bytesRead, NULL

    xor ecx, ecx
    mov cl, byte ptr [bytesRead]

    lea edi, [buffer]
    mov esi, edi

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

        inc esi
        inc edi

        loop @@loop2

    ; Atualize o valor de ecx para o número correto de bytes lidos
    mov ecx, [bytesRead]

    invoke WriteFile, ebx, addr buffer, ecx, addr bytesWritten, NULL

    invoke CloseHandle, edi
    invoke CloseHandle, ebx

    jmp menuLoop

criptoanalise:
    invoke StdOut, addr filePrompt
    invoke StdIn, addr inputFileBuffer, 256

    jmp menuLoop

exitProgram:
    invoke ExitProcess, 0

end start

我认为问题出在atodw函数上:

invoke StdOut, addr keyPrompt
invoke StdIn, addr keyBuffer, 256

invoke atodw, addr keyBuffer
mov ecx, eax
33qvvth1

33qvvth11#

invoke atodw, addr keyBuffer
mov eax, eax

mov eax, eax将EAX迁移到EAX没有什么意义
看看你如何使用密钥(sub al, byte ptr [keyBuffer]add al, byte ptr [keyBuffer]),你应该这样写:

invoke atodw, addr keyBuffer
mov    byte ptr [keyBuffer], al

还有更多的事情发生在这里!

xor ecx, ecx
mov cl, byte ptr [bytesRead]
  • BytesRead* 是限制为512(sizeof buffer)的双字。你不应该把它读成一个字节!这样做可能会丢失256或512个字节!

简单地写为mov ecx, [bytesRead]

lea edi, [buffer]
...              <<< the loop
invoke CloseHandle, edi
invoke CloseHandle, ebx

一旦EDI中的句柄通过在循环中使用该寄存器而被销毁,您将无法成功关闭文件。
你可以在堆栈上保留句柄:

lea  edi, [buffer]
push edi
...              <<< the loop
pop  edi
invoke CloseHandle, edi
invoke CloseHandle, ebx

相关问题