x86-64汇编打印1-10陷入死循环求助:cl寄存器无法递增
解决x86-64汇编打印1-10的死循环问题
问题根源
- 系统调用破坏寄存器:Linux x86-64的
syscall指令会直接覆盖rcx和r11寄存器,你代码里用的cl是rcx的低8位,每次syscall后cl的值都会被冲掉,inc cl的修改完全无效,循环条件永远满足,直接陷入死循环。 - 寄存器未初始化:
cl一开始未赋值,初始值是随机垃圾数据,第一次执行add byte[number], cl就把输出缓冲区搞乱了。 - 累加逻辑错误:每次循环给
number累加cl,导致数值不断叠加(比如第一次加1,第二次加2,结果变成'0'+1+2='3'),根本无法逐个输出目标数字。 - 未处理两位数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
相关产品推荐
相关产品推荐

