如何修复汇编语言实现的Caesar Cipher多位数密钥读取问题?
凯撒密码汇编程序密钥识别问题修复方案
问题描述
用汇编语言实现的凯撒密码程序,支持输入文件名、输出文件名和密钥,但输入两位数密钥(如14、15)时,程序仅识别第一位数字(如1),导致加解密逻辑错误。
问题根源
你怀疑atodw相关代码的方向是对的,但核心错误是:虽然用atodw把密钥字符串转换成了数值,但加解密循环里根本没用到这个转换后的数值,反而直接读取keyBuffer的第一个字节(也就是密钥字符串的第一个字符ASCII码)。
比如解密循环里的代码:
sub al, byte ptr [keyBuffer]
当输入密钥"14"时,keyBuffer里存的是'1','4',0Dh,0Ah,...,这里取的是'1'的ASCII值(49),而不是转换后的数值14,自然只会生效第一位数字的效果。
同时你用invoke atodw, addr keyBuffer; mov ecx, eax把转换后的密钥存到了ecx,但后面立刻执行xor ecx, ecx; mov cl, byte ptr [bytesRead]把ecx覆盖成了文件读取的字节数,这个转换后的密钥数值完全没被使用。
修复步骤
1. 添加存储密钥数值的变量
在.data段新增一个双字变量,用来保存转换后的密钥数值:
.data ; ... 原有变量 ... keyValue dd 0 ; 新增:存储转换后的密钥数值
2. 保存转换后的密钥数值
在读取密钥并调用atodw后,把结果存入keyValue,而不是存到会被覆盖的ecx:
invoke StdOut, addr keyPrompt invoke StdIn, addr keyBuffer, 256 invoke atodw, addr keyBuffer mov keyValue, eax ; 把转换后的数值存入keyValue
3. 在加解密循环中使用正确的密钥数值
修改解密和加密循环里的操作,用keyValue的低字节(因为密钥范围1-20,远小于256)代替keyBuffer:
- 解密循环(
@@loop1):
mov al, byte ptr [esi] sub al, byte ptr [keyValue] ; 用转换后的数值代替keyBuffer mov byte ptr [edi], al
- 加密循环(
@@loop2):
mov al, byte ptr [esi] add al, byte ptr [keyValue] ; 用转换后的数值代替keyBuffer mov byte ptr [edi], al
4. 可选:密钥范围校验(增强健壮性)
可以在转换密钥后添加范围校验,确保密钥在1-20之间,比如:
invoke atodw, addr keyBuffer cmp eax, 1 jb menuLoop ; 小于1则返回菜单重输 cmp eax, 20 ja menuLoop ; 大于20则返回菜单重输 mov keyValue, eax
修复后核心代码片段示例
以解密函数为例,修改后的部分代码:
descriptografar: 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 ; 新增密钥范围校验 cmp eax, 1 jb descriptografar cmp eax, 20 ja descriptografar mov keyValue, 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 [keyValue] ; 使用正确的密钥数值 mov byte ptr [edi], al inc esi inc edi loop @@loop1 mov ecx, [bytesRead] invoke WriteFile, ebx, addr buffer, ecx, addr bytesWritten, NULL invoke CloseHandle, edi invoke CloseHandle, ebx jmp menuLoop
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

