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

x86-64汇编打印1-10陷入死循环求助:cl寄存器无法递增

解决x86-64汇编打印1-10的死循环问题

问题根源

  1. 系统调用破坏寄存器:Linux x86-64的syscall指令会直接覆盖rcx和r11寄存器,你代码里用的cl是rcx的低8位,每次syscall后cl的值都会被冲掉,inc cl的修改完全无效,循环条件永远满足,直接陷入死循环。
  2. 寄存器未初始化:cl一开始未赋值,初始值是随机垃圾数据,第一次执行add byte[number], cl就把输出缓冲区搞乱了。
  3. 累加逻辑错误:每次循环给number累加cl,导致数值不断叠加(比如第一次加1,第二次加2,结果变成'0'+1+2='3'),根本无法逐个输出目标数字。
  4. 未处理两位数10:你需要打印1到10,但原代码只处理了0-9的单字符,10属于两位数,需要单独处理。

修复后的代码

section .data
    number db '0'  ; 初始化为ASCII '0'
    nl db 10       ; 换行符
    ten_str db '10' ; 存储10的ASCII字符串

section .text
    global _start

_start:
    ; 使用不会被syscall破坏的寄存器作为计数器(r8b不受syscall影响)
    mov r8b, 1      ; 从1开始计数

.loop_print_single:
    ; 计算当前数字的ASCII值:'0' + 计数器
    mov al, '0'
    add al, r8b
    mov byte[number], al

    ; 调用sys_write打印单个数字
    mov rax, 1      ; sys_write的系统调用号
    mov rdi, 1      ; 标准输出
    mov rsi, number ; 缓冲区地址
    mov rdx, 1      ; 输出长度1字节
    syscall

    inc r8b
    cmp r8b, 9      ; 打印到9后跳出单字符循环
    jle .loop_print_single

    ; 单独打印10
    mov rax, 1
    mov rsi, ten_str
    mov rdx, 2      ; 10占2字节
    syscall

    ; 打印换行
    mov rax, 1
    mov rsi, nl
    mov rdx, 1
    syscall

    ; 退出程序
    mov rax, 60
    xor rdi, rdi
    syscall

核心修复细节

  • 选对寄存器:使用r8b(或rbx、rbp这类被调用者保存寄存器),这些寄存器不会被syscall指令破坏,计数器的值能稳定保留。
  • 正确生成ASCII值:每次循环重新计算当前数字的ASCII值,避免累加错误。
  • 处理两位数10:单独定义字符串存储"10",输出时指定长度为2。
  • 明确循环范围:循环从1到9,之后单独处理10,完全匹配打印1-10的需求。

额外提示

Linux x86-64系统调用规则:rax存储调用号,rdi/rsi/rdx/r10/r8/r9传递参数;syscall会破坏rcx和r11,绝对不要用这两个寄存器存储需要保留的数据。

内容的提问来源于stack exchange,提问作者Adrián Ramírez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 23:55:12