英文:
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
... <<< the loop
pop edi
invoke CloseHandle, edi
invoke CloseHandle, ebx
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论