汇编实现凯撒加密时ASCII字符校验异常求助
凯撒加密程序的字符校验故障排查与修复
我刚接触汇编语言,正在编写一款支持用户指定密钥与内容的凯撒加密程序。要求密钥和内容必须为a-z或A-Z字符,为此编写了简单算法校验其ASCII值是否在对应范围内,但即便输入正常的a-z/A-Z字符,校验仍返回错误。
以下是算法的最小可复现示例,输入字符'a'却仍返回错误,查阅ASCII表后仍无法定位问题:
section .text global _start _start: cmp byte [char], 122 jg _error cmp byte [char], 96 jg _success cmp byte [char], 90 jg _error cmp byte [char], 64 jg _success jmp _error _success: mov rax, 1 mov rdi, 1 mov rsi, success mov rdx, len_success syscall xor rbx, rbx jmp _exit _error: mov rax, 1 mov rdi, 2 mov rsi, error mov rdx, len_error syscall mov rbx, 1 jmp _exit _exit: mov rax, 60 mov rdi, rbx syscall section _data char db 'a' error db "Error" len_error equ $ - error success db "Success" len_success equ $ - success
实际处理文本的算法如下:
_process_text_input: cmp byte [text_input], 10 je _no_text_error xor rbx, rbx jmp _pti_loop _pti_loop: cmp rbx, [len_text_input] jg _pti_end mov al, [text_input+rbx] cmp al, 97 jl _process_capital_char cmp al, 122 jg _bad_text_error add al, [key] cmp al, 122 jg _fix_overhang mov byte [output+rbx], al inc rbx jmp _pti_loop _process_capital_char: cmp byte [text_input+rbx], 90 jg _bad_text_error cmp byte [text_input+rbx], 65 jl _bad_text_error mov al, [text_input+rbx] add al, [key] cmp al, 90 jg _fix_overhang mov byte [output+rbx], al inc rbx jmp _pti_loop _fix_overhang: sub al, 26 mov byte [output+rbx], al inc rbx jmp _pti_loop _pti_end: ret
问题根源与修复方案
最小复现示例的核心问题
- 段名语法错误:NASM中数据段的正确声明是
section .data或.data,你写的section _data是无效段名,导致char变量未被正确加载到数据段,程序读取的是随机垃圾值,自然触发错误。把section _data改成section .data即可解决基础问题。 - 校验逻辑顺序冗余:现有校验逻辑虽然能工作,但顺序混乱易出错。优化后的清晰校验逻辑如下:
_start: cmp byte [char], 65 jl _error ; 小于'A',错误 cmp byte [char], 90 jle _success ; 在'A'-'Z'之间,成功 cmp byte [char], 97 jl _error ; 在'Z'-'a'之间,非字母,错误 cmp byte [char], 122 jle _success ; 在'a'-'z'之间,成功 jmp _error
实际算法的问题与修复
- 重复内存访问:
_process_capital_char中重复读取[text_input+rbx],可以直接复用_pti_loop中已加载到al的字符值,减少不必要的内存操作。 - 密钥处理错误:直接
add al, [key]会使用密钥字符的ASCII值作为偏移量(比如输入密钥'3'会加51),这完全不符合凯撒加密的偏移逻辑。需要先将密钥字符转换为0-25的数值:; 假设密钥是小写字符,转换为偏移量 mov bl, [key] sub bl, 97 mov [key_num], bl - 循环边界判断错误:
cmp rbx, [len_text_input]后用jg会漏掉rbx等于长度的情况,应该改用jge,此时所有字符已处理完毕,需退出循环。 - 代码冗余优化:合并重复的存储与跳转逻辑,让代码更简洁易维护。
修复后的实际算法示例:
_process_text_input: cmp byte [text_input], 10 je _no_text_error xor rbx, rbx _pti_loop: cmp rbx, [len_text_input] jge _pti_end ; 长度相等时退出循环 mov al, [text_input+rbx] ; 检查小写字母范围 cmp al, 97 jge .check_lower_bound ; 检查大写字母范围 cmp al, 65 jl _bad_text_error cmp al, 90 jg _bad_text_error ; 处理大写字母偏移 add al, [key_num] cmp al, 90 jle .store_result sub al, 26 jmp .store_result .check_lower_bound: cmp al, 122 jg _bad_text_error ; 处理小写字母偏移 add al, [key_num] cmp al, 122 jle .store_result sub al, 26 .store_result: mov byte [output+rbx], al inc rbx jmp _pti_loop _pti_end: ret
内容的提问来源于stack exchange,提问作者B3d3vtvng
相关产品推荐
相关产品推荐

