如何修复我的汇编语言凯撒密码实现,以便读取多位数字密钥?

huangapple go评论57阅读模式
英文:

How can I fix my Caesar Cipher implementation in assembly language to read multi-digit keys?

问题

问题可能出现在 atodw 函数上:

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

invoke atodw, addr keyBuffer
mov ecx, eax

atodw 函数似乎被用来将用户输入的字符串(代表密钥的部分)转换为一个整数值。然而,从你提供的代码来看,这个函数没有被定义,因此无法确定它的实际实现是什么。

在你的代码中,keyBuffer 存储了用户输入的密钥,但是如何将它正确地转换为一个整数值取决于 atodw 函数的实现。如果 atodw 函数没有正确处理多位数的情况,那么只会读取到第一个数字。

要解决这个问题,你需要确保 atodw 函数能够正确地将整个密钥字符串转换为整数,而不仅仅是第一个字符。你可以检查 atodw 函数的定义并确保它按照预期工作,或者考虑使用其他方法来将字符串转换为整数,例如使用标准库函数 atoi(在C/C++中)或类似的方法。

英文:

My code implements the Caesar Cipher, it asks the user the name of the input file which contains the string i want to be encrypted/decrypted, the name of the output file and the key/cipher, my problem is that it is only reading the first number of the key, if i give it a number with two digits as a key then it only reads the first, like 14, 15, it only reads the 1. How can i fix this? Here is the code:

.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

I think the problem is with the atodw function:

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

invoke atodw, addr keyBuffer
mov ecx, eax

答案1

得分: 1

"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" 将 ECX 设置为零

mov ecx, [bytesRead]

BytesRead 是一个限制为 512 的 dword(sizeof buffer)。您不应该将其读取为字节!这样做会有丢失 256 或 512 字节的风险!

lea edi, [buffer]
...              <<< 循环部分
invoke CloseHandle, edi
invoke CloseHandle, ebx

您将无法成功关闭文件,因为在循环中使用 EDI 寄存器会销毁其中的句柄。您可以在堆栈上保留句柄:

lea edi, [buffer]
push edi
...              <<< 循环部分
pop edi
invoke CloseHandle, edi
invoke CloseHandle, ebx
英文:

> invoke atodw, addr keyBuffer
> mov eax, eax

mov eax, eax There's little point in moving EAX to EAX

Seeing how you use the key (sub al, byte ptr [keyBuffer] and add al, byte ptr [keyBuffer]), you should write:

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

There's more going on here!

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

BytesRead is a dword that is limited to 512 (sizeof buffer). You should not be reading this as a byte! You risk loosing 256 or 512 bytes from doing so!
Simply write mov ecx, [bytesRead]

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

You won't be able to successfully close the file once the handle in EDI gets destroyed by using that register in the loop(s).
You could preserve the handle on the stack:

lea  edi, [buffer]
push edi
...              &lt;&lt;&lt; the loop
pop  edi
invoke CloseHandle, edi
invoke CloseHandle, ebx

huangapple
  • 本文由 发表于 2023年5月29日 02:00:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352878.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定