汇编调用C加密函数实现字符串移位仅输出首字符的修复咨询
问题修复方案
核心错误点
- 缓冲区分配过小:
getMessage和encrypted仅分配了8字节(resq 1),无法存储普通长度的输入字符串,且长度定义len逻辑错误,没有正确获取输入字符串的实际长度 - 字符偏移计算错误:字符串每个字符占1字节,代码中使用
rcx*4作为偏移,每处理一个字符就向后跳4字节,只会读取到首字符,后续字符全部错位 - 参数传递错误:调用
encrypt时直接读取8字节内存到rdi,没有正确传递单字节字符;存储返回值时直接写入整个8字节rax,会破坏后续内存 - 加密后的字符串没有添加字符串结束符
\0,导致printf输出时无法正确识别字符串边界
修复后完整代码
extern printf, scanf extern encrypt global main section .data format db '%ld',0 format3 db "%s",10,0 format_str db "%s",0 message1: db "1. Input New Message",10,0 message2: db "Enter a number of shift:",10,0 section .bss getMessage: resb 1024 ; 分配1K缓冲区存储输入字符串 shiftNum resq 1 encrypted resb 1024 ; 分配1K缓冲区存储加密后字符串 str_len resq 1 ; 存储输入字符串实际长度 section .text main: mov rdx, message1 call print call scanMessage mov [str_len], rax ; 保存sys_read返回的实际输入长度 dec qword [str_len] ; 去掉sys_read读入的末尾换行符 mov rdx, message2 call print call scanChoice mov rdx, getMessage call print mov r8, getMessage mov rbx, [shiftNum] mov rdx, [str_len] call shift mov rdx, encrypted call print mov rax, 60 mov rdi, 0 syscall ; 正常退出程序 ; end main scanChoice: mov rdi, format mov rsi, shiftNum mov rax, 0 call scanf ret scanMessage: mov rax, 0 mov rdi, 0 mov rsi, getMessage mov rdx, 1024 syscall ret print: mov rdi,format3 mov rsi,rdx mov rax,0 call printf ret shift: mov rcx, 0 loop: cmp rcx, rdx jge done movzx rdi, byte [r8 + rcx] ; 仅读取1字节字符,零扩展到rdi mov rsi, rbx call encrypt mov byte [encrypted + rcx], al ; 仅保存返回的1字节加密字符 inc rcx jmp loop done: mov byte [encrypted + rcx], 0 ; 添加字符串结束符 ret
改动说明
- 扩大了输入、输出缓冲区到1024字节,新增变量存储输入字符串的实际长度,去掉了
sys_read读取的末尾换行符 - 移除了偏移地址的
*4计算,按单字节1单位偏移读取、存储字符 - 用
movzx指令读取单字节字符传递给encrypt,返回时仅存储rax低8位的al寄存器(即加密后的字符) - 加密结束后在字符串末尾补
\0,保证printf可以正常输出完整字符串 - 新增正常退出程序的系统调用,避免程序执行结束后段错误
内容的提问来源于stack exchange,提问作者prxx20
相关产品推荐
相关产品推荐

