ASM实现字符串转整数触发段错误,求问题定位与修复方案
NASM ELF 字符串转整数段错误问题定位与修复
常见错误原因分析
从你描述的「单数字版本正常,添加AtoI函数后出现段错误」来看,问题大概率出在以下几个方面:
- 栈帧管理错误:AtoI函数未正确初始化/恢复栈帧,导致返回时跳转到非法内存地址
- 内存访问越界:循环处理字符串时未正确判断终止条件,访问了缓冲区外的内存
- 调用约定违反:修改了被调用者保存寄存器(如
ebx、esi)但未恢复,破坏主程序栈环境 - 参数传递错误:传递给AtoI的字符串指针无效,导致函数读取非法内存
修复示例代码
以下是可正常运行的完整实现,包含输入、AtoI转换流程,你可以对比自身代码排查差异:
section .data prompt db 'Enter a number: ', 0 len_prompt equ $ - prompt section .bss input_buf resb 20 ; 预留足够缓冲区存储输入 section .text global _start _start: ; 输出提示信息 mov eax, 4 mov ebx, 1 mov ecx, prompt mov edx, len_prompt int 0x80 ; 读取用户输入 mov eax, 3 mov ebx, 0 mov ecx, input_buf mov edx, 20 int 0x80 ; 调用AtoI函数:eax传入字符串指针,返回值存于eax mov eax, input_buf call atoi ; 此处可添加结果输出逻辑(如将整数转字符串打印),暂省略 exit: mov eax, 1 xor ebx, ebx int 0x80 ; AtoI函数:输入eax=字符串指针,输出eax=转换后的整数 ; 遇非数字字符终止转换 atoi: push ebx push esi mov esi, eax ; esi保存字符串指针 xor eax, eax ; 初始化结果为0 xor ebx, ebx ; ebx暂存当前字符 atoi_loop: mov bl, [esi] ; 读取当前字符 inc esi ; 指针后移 ; 判断是否为数字字符(0-9) cmp bl, '0' jb atoi_end cmp bl, '9' ja atoi_end ; 计算:eax = eax*10 + (bl - '0') imul eax, 10 sub bl, '0' add eax, ebx jmp atoi_loop atoi_end: pop esi pop ebx ret
关键修复点说明
- 寄存器保护:AtoI函数开头
push ebx、push esi,结尾pop esi、pop ebx,符合Linux x86调用约定(被调用者需保存ebx、esi、edi、ebp) - 循环终止逻辑:明确判断字符是否在
'0'-'9'范围内,不在则立即终止循环,避免访问非法内存 - 输入缓冲区安全:预留20字节缓冲区,读取输入时限制长度,防止缓冲区溢出
- 参数与返回值约定:采用简单自定义约定(eax传参、eax返回结果),也可按需改用标准cdecl约定(参数压栈传递)
编译运行命令
nasm -f elf32 atoi.asm -o atoi.o ld -m elf_i386 atoi.o -o atoi ./atoi
内容的提问来源于stack exchange,提问作者dev_404
相关产品推荐
相关产品推荐

