如何在NASM汇编中提取字符串数字并输出?新手代码遇超时问题
解决NASM汇编提取字符串数字的死循环及逻辑问题
你的代码核心问题
- 死循环根源:
digits数组没加0结尾,导致next_digit里的cmp dl, 0永远不会触发跳转,一旦遇到非数字字符,就会无限遍历digits。 - 寄存器冲突:
mov al, byte [eax]直接覆盖了eax的低8位,破坏了原字符串的地址指针(eax本来存的是message起始地址)。dl临时存digits字符,同时edx又用来统计数字个数,会把计数覆盖掉。
- 输出逻辑错误:
mov edx, edx是无效操作,而且你只是替换原字符串里的数字,非数字字符还留在原位置,输出时会把这些杂项也打出来,根本不是“提取数字”的效果。 - 非数字处理缺失:遇到非数字字符时,没移动原字符串指针,导致一直卡在同一个字符上,也是死循环的诱因。
修正后的代码
section .data message db 'Hell34o, w2or5ld', 0 output_buf times 100 db 0 ; 专门开缓冲区存提取出的数字 section .text global _start _start: mov esi, message ; esi: 原字符串的遍历指针 mov edi, output_buf ; edi: 输出缓冲区的写入指针 mov ecx, 0 ; ecx: 数字计数器,同时用来存求和结果 traverse_string: mov al, byte [esi] ; 取当前字符 cmp al, 0 ; 判断是否到字符串结尾 je print_digits ; 到结尾就跳去打印 ; 直接通过ASCII范围判断是不是数字:'0'(0x30)到'9'(0x39) cmp al, '0' jb next_char ; 比'0'小,不是数字,跳过 cmp al, '9' ja next_char ; 比'9'大,不是数字,跳过 ; 是数字的情况:存缓冲区+累加求和 mov byte [edi], al ; 把数字字符写入缓冲区 inc edi ; 缓冲区指针后移 sub al, '0' ; ASCII转成真实数字值 add ecx, eax ; 累加到ecx里 inc esi ; 原字符串指针后移 jmp traverse_string next_char: inc esi ; 非数字,直接移到下一个字符 jmp traverse_string print_digits: ; 计算提取出的数字长度:当前缓冲区地址 - 起始地址 mov edx, edi sub edx, output_buf ; 调用sys_write输出数字 mov eax, 4 mov ebx, 1 mov ecx, output_buf int 0x80 ; 输出求和结果(处理小于100的情况,简单实现) mov eax, ecx ; eax存求和结果 mov edi, output_buf ; 复用缓冲区存结果字符串 mov ecx, 0 ; 统计结果的位数 convert_sum: xor edx, edx mov ebx, 10 div ebx ; eax=商,edx=余数 add dl, '0' ; 余数转ASCII mov byte [edi+ecx], dl inc ecx cmp eax, 0 jne convert_sum ; 输出换行分隔数字和求和结果 mov eax, 4 mov ebx, 1 mov ecx, 0xA ; 换行符ASCII码 mov edx, 1 int 0x80 ; 反转结果字符串(因为转ASCII时是倒序存的) mov esi, output_buf mov ebx, ecx dec ebx reverse_loop: cmp esi, edi+ebx jge print_sum mov al, byte [esi] mov dl, byte [edi+ebx] mov byte [esi], dl mov byte [edi+ebx], al inc esi dec ebx jmp reverse_loop print_sum: mov eax, 4 mov ebx, 1 mov ecx, output_buf mov edx, ecx ; ecx是结果位数,赋值给edx int 0x80 exit_program: ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80
关键修正说明
- 避免死循环:直接用ASCII范围判断数字,比遍历
digits数组高效,还从根源避免了数组无结尾的问题。 - 寄存器合理分配:用
esi存原字符串指针、edi存输出缓冲区指针,彻底避免寄存器互相覆盖的问题。 - 提取逻辑优化:单独用缓冲区存数字,确保输出内容只有提取到的数字。
- 实现求和:把ASCII数字转成数值后累加,最后把求和结果转成ASCII输出,完成你最终的目标。
内容的提问来源于stack exchange,提问作者isaac
相关产品推荐
相关产品推荐

