x86汇编encryptStr字符串加密函数实现代码合理性咨询
问题结论
你提交的代码完全不符合题目要求,没有实现任何题目指定的加密和统计逻辑,属于功能完全错位的实现,具体问题清单如下:
- 基础命名错误:题目要求实现的函数名为
encryptStr,你的代码里拼写为encriptStr,链接时会找不到对应符号 - 核心逻辑完全偏离:你写的是九进制字符串转整数的乘法计算逻辑,既没有实现「字母字符加1、非字母保持不变」的加密规则,也没有实现三个指定指标的统计
- 未定义内存引用:代码中使用了
rSum、digit两个未在.data/.bss段声明的内存标签,运行时会触发段错误直接崩溃 - 参数处理不全:按照x86-64 System V标准调用约定,函数的四个参数依次存放在
rdi(inStr)、rsi(ltrCnt地址)、rdx(digitCnt地址)、rcx(strLen地址),你的代码只使用了前两个参数,后两个统计值的地址完全没处理 - 循环逻辑错误:遍历字符时只处理'0'和'1',遇到其他任意字符直接跳出循环,根本无法遍历完整个NULL结尾的字符串
- 数据长度不匹配:题目明确要求三个统计值是无符号双字(32位),你的代码往对应地址写入64位qword,会造成相邻内存的越界覆写
- 未处理初始值要求:题目明确说明传入的三个计数变量未初始化为0,你的代码没有先给这三个变量置0再计数,统计结果完全不可控
- 存在无效代码:函数末尾多写了一个永远执行不到的
ret指令,还存在重复赋值r11寄存器的无效操作
符合要求的实现参考
本实现不需要额外的全局/静态内存变量,所有计数都用寄存器暂存,遍历完成后统一写回参数地址,无多余内存访问,效率符合要求。
寄存器使用规划(遵循调用约定规则)
仅对用到的被调用者保存寄存器做入栈/出栈恢复:
rbx:暂存输入字符串首地址r12:暂存字母计数r13:暂存数字计数r14:暂存遍历偏移/字符串总长度rax:临时存放当前读取的字符
r10、r11、rax属于调用者保存寄存器,函数内无需额外做保存恢复操作。
逻辑说明
- 进入函数后暂存传入的参数地址,同时将三个计数寄存器初始化为0
- 逐字节读取字符串字符:
- 遇到NULL字符时终止遍历
- 总长度计数直接+1
- 判断字符是否为大写字母(
A`Z`)或小写字母(`a`z):是则字母计数+1,字符值加1后写回原位置(和题目示例一致,Z/z加1后直接变为[/{,不需要做回绕到a/A的处理) - 否则判断是否为数字(
0~9):是则数字计数+1,字符保持不变 - 其余字符直接跳过,不修改、不额外计数
- 遍历结束后,把三个计数值分别写入对应参数指向的32位内存地址,恢复保存的寄存器后返回
对应汇编代码
; 函数实现:encryptStr ; 参数遵循x86-64 System V调用约定: ; rdi = inStr 输入字符串首地址 ; rsi = ltrCnt 字母计数变量地址(32位无符号) ; rdx = digitCnt 数字计数变量地址(32位无符号) ; rcx = strLen 字符串长度变量地址(32位无符号) global encryptStr encryptStr: ; 保存用到的被调用者保存寄存器 push rbx push r12 push r13 push r14 ; 暂存参数、初始化计数为0 mov rbx, rdi ; 存字符串首地址到rbx xor r12, r12 ; r12 = 字母计数,初始0 xor r13, r13 ; r13 = 数字计数,初始0 xor r14, r14 ; r14 = 遍历偏移/字符串总长度,初始0 loop_start: mov al, byte [rbx + r14] ; 读取当前字符 test al, al ; 判断是否为NULL结尾 jz loop_end inc r14 ; 总长度+1(已确认当前字符不是NULL,不计入结尾符) ; 判断是否为字母 cmp al, 'A' jb check_digit ; ASCII码小于'A',跳去判断是不是数字 cmp al, 'Z' jbe is_letter ; 在'A'~'Z'区间,是大写字母 cmp al, 'a' jb check_digit ; 大于'Z'小于'a',不是字母,跳去判断数字 cmp al, 'z' jbe is_letter ; 在'a'~'z'区间,是小写字母 jmp next_char ; 大于'z',不是字母数字,直接处理下一个字符 is_letter: inc al ; 字母执行加1加密 mov byte [rbx + r14 - 1], al ; 写回加密后的字符(r14已经自增,偏移减1定位到当前字符位置) inc r12 ; 字母计数+1 jmp next_char check_digit: cmp al, '0' jb next_char ; ASCII码小于'0',不是数字 cmp al, '9' ja next_char ; ASCII码大于'9',不是数字 inc r13 ; 数字计数+1 next_char: jmp loop_start loop_end: ; 把三个计数写回对应地址,使用32位寄存器操作匹配无符号双字要求 mov [rsi], r12d ; 写入字母计数 mov [rdx], r13d ; 写入数字计数 mov [rcx], r14d ; 写入字符串总长度 ; 恢复保存的寄存器 pop r14 pop r13 pop r12 pop rbx ret
你原来写的printString函数逻辑正确,可以直接保留使用,调用时注意修正函数名拼写错误即可。用题目给出的测试用例Hello Zoo 12验证,加密后输出为Ifmmp [pp 12,三个统计值分别为字母数8、数字数2、总长度12,完全符合题目要求。
内容的提问来源于stack exchange,提问作者user18875739
相关产品推荐
相关产品推荐

