.586汇编下使用gets()获取字符串转十进制的实现问题
x86(.586 32位)汇编字符串转十进制数值实现方案
你提到的两个基础认知都是正确的:
- 标准C库的
gets()函数调用完成后,输入字符串的首地址确实会存储在eax寄存器中 - 单个ASCII数字字符转对应十进制值的核心操作就是减去48(即ASCII编码中
'0'的编码值0x30),这个思路没有问题,你测试未生效通常是缺少了多位数的累加处理逻辑,或操作对象错误导致的。
完整转换步骤
- 首先初始化寄存器:用
ecx作为字符串遍历指针,初始赋值为eax的值;用ebx存储最终转换得到的整数,初始设为0 - 进入循环逐位处理:
- 读取
ecx指针指向的1字节内容到8位寄存器dl,判断该值是否为0x0(字符串结束符'\0'),若是则结束转换 - 将
ebx中当前存储的数值乘以10,给新的数位腾出个位空间 - 将
dl中的ASCII字符减去'0'(即48),得到当前位的十进制数值 - 将转换后的数值零扩展为32位后,累加至
ebx中 ecx自增1,指向下一个字符,回到循环开头
- 读取
- 转换完成后,
ebx中存储的就是输入字符串对应的十进制整数
常见错误排查(对应你提到的减48未生效的场景):
- 操作对象错误:直接对
eax寄存器本身(存储的是字符串地址)做减法,而非对eax指向的内存地址中的字符值做减法- 缺少进位逻辑:仅对单个字符做了减法,未执行乘10累加的操作,只能得到单个字符对应的数值,无法得到多位数的完整结果
- 未做结束判断:遍历到字符串结束符后仍继续读取后续内存的垃圾值,导致最终结果异常
示例核心代码(NASM语法,32位环境)
; 调用gets()后,eax已存储输入字符串首地址 mov ecx, eax ; 初始化字符串遍历指针 xor ebx, ebx ; 最终结果寄存器清零 convert_loop: mov dl, [ecx] ; 读取当前字符到dl test dl, dl ; 判断是否为字符串结束符 jz convert_done ; 是结束符则跳出循环 imul ebx, ebx, 10 ; 现有结果乘10 sub dl, '0' ; ASCII字符转十进制数字 movzx edx, dl ; 8位值零扩展为32位,避免加法溢出 add ebx, edx ; 累加当前位到结果 inc ecx ; 指针后移一位 jmp convert_loop convert_done: ; 此时ebx寄存器中即为转换完成的十进制整数
如果按照上述逻辑调整后仍然无法得到正确结果,你可以附上你的完整代码拆解内容做进一步排查。
内容的提问来源于stack exchange,提问作者Topher
相关产品推荐
相关产品推荐

