You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 13:08:11