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

ARM 32位汇编实现1到n打印异常求助:仅输出1

问题排查与修正

错误原因

代码仅打印1次的核心问题是ARM函数调用约定的寄存器使用规则:
printf属于外部函数,按照ARM的AAPCS调用约定,r0-r3是临时寄存器,外部函数可以随意修改这些寄存器的值。你把输入的n存在r2中,第一次调用printf后,r2的值已被覆盖,后续循环的cmp r3,r2实际是拿r3和一个被破坏的无效值比较,导致循环直接终止。

另外还有一个小问题:原循环用blt(小于则跳转),当r3等于输入的n时,条件不满足,会跳过打印n本身(比如输入5只会打印1-4)。

修正后的代码

.text
.global main

main:
    @ 保存被调用者保存寄存器r4和链接寄存器lr到栈
    push {r4, lr}

    adr r0,format
    ldr r1,=number
    bl scanf

    @ 将输入的n存入r4(被调用者保存寄存器,printf不会修改它)
    ldr r4,=number
    ldr r4,[r4]

    mov r3,#1

loop:
    mov r1,r3
    adr r0,format1
    bl printf
    add r3,r3,#1
    cmp r3,r4
    ble loop   @ 改成小于等于,确保打印到n本身

    @ 正常退出,返回值0
    mov r0,#0
    pop {r4, pc}  @ 恢复寄存器并返回


format: .asciz "%d"
format1: .asciz "%d\n"  @ 标准换行符写法

.data
    number: .word 0

关键修正点

  • 寄存器选择:把n的值移到r4中,r4属于被调用者保存寄存器,外部函数调用后其值会被保留。
  • 栈帧处理:开头push {r4, lr}保存寄存器,结尾pop {r4, pc}恢复并返回,替代原代码的bl exit,更符合ARM程序的规范写法。
  • 循环条件:将blt改为ble,确保循环执行到r3等于n时仍会打印,覆盖1到n的所有数字。
  • 换行符修正:把format1中的换行改为标准的\n,避免字符串解析问题。
  • 退出码修正:将原mov r0,#1改为mov r0,#0,0是程序正常退出的标准返回码。

编译执行

仍使用你原来的命令:

arm-linux-gnueabi-gcc print_first_n.S -o print_first_n
qemu-arm -L /usr/arm-linux-gnueabi ./print_first_n

输入5后,会正常打印1到5的所有数字。

内容的提问来源于stack exchange,提问作者ggz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:00:06