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

ARMv8如何打印数值?行/词/字符统计代码无输出求助

ARMv8汇编统计行/单词/字符数后无法输出的问题解决

我写了一段ARMv8汇编代码,用来统计输入文件的行数、单词数和字符数并输出到stdout,但测试时没有任何内容输出。作为ARM新手,想请教:怎么在ARMv8中打印lLineCount、lWordCount、lCharCount的数值?打印指令应该放在哪里?

现有代码

.section        .data
lLineCount:     .quad   0
lWordCount:     .quad   0
lCharCount:     .quad   0
iInWord:        .quad   0

        .section        .text
        .global        main

main:
        stp     x29, x30, [sp, -16]!
        mov     x29, sp
        adrp    x0, lLineCount
        add     x0, x0, :lo12:lLineCount
        ldr     x1, [x0]
        ldr     x0, [sp, 16]
        bl      getchar
        cmp     x0, #-1
        b.eq    .L2
        adrp    x0, lCharCount
        add     x0, x0, :lo12:lCharCount
        ldr     x1, [x0]
        add     x1, x1, 1
        str     x1, [x0]
        adrp    x0, iInWord
        add     x0, x0, :lo12:iInWord
        ldr     x1, [x0]
        cmp     x1, 0
        b.ne    .L3
        adrp    x0, lWordCount
        add     x0, x0, :lo12:lWordCount
        ldr     x1, [x0]
        add     x1, x1, 1
        str     x1, [x0]
        mov     x0, 0
        str     x0, [x0]
        b       .L4

.L3:
        adrp    x0, lWordCount
        add     x0, x0, :lo12:lWordCount
        ldr     x1, [x0]
        add     x1, x1, 1
        str     x1, [x0]
        mov     x0, 0
        str     x0, [x0]

.L4:
        adrp    x0, lLineCount
        add     x0, x0, :lo12:lLineCount
        ldr     x1, [x0]
        add     x1, x1, 1
        str     x1, [x0]
        b       .L1

.L2:
        adrp    x0, lLineCount
        add     x0, x0, :lo12:lLineCount
        ldr     x1, [x0]
        ldr     x0, [sp, 16]
        bl      printf
        mov     x0, 0
        ldp     x29, x30, [sp], 16
        ret

.L1:
        adrp    x0, lLineCount
        add     x0, x0, :lo12:lLineCount
        ldr     x1, [x0]
        ldr     x0, [sp, 16]
        bl      getchar
        cmp     x0, #-1
        b.ne    .L3

问题分析

你的代码有两个核心问题导致无法输出:

  1. printf使用错误:
    • 没有定义printf需要的格式字符串,直接调用printf时x0传递的是[sp,16]的值,这是错误的地址,根本不是格式字符串。
    • ARMv8的调用约定中,printf的第一个参数(x0)必须是格式字符串的地址,后续参数(x1、x2、x3...)对应格式字符串里的占位符。
  2. 统计逻辑存在bug:
    • 没有判断字符类型(比如空格、换行、制表符)来区分单词,导致单词数统计错误。
    • iInWord的赋值逻辑混乱,比如mov x0,0; str x0,[x0]是把0写到x0指向的地址,但此时x0是lWordCount的地址,这会直接把单词数清零,完全错误。
    • 循环跳转逻辑混乱,.L1和.L3的跳转导致统计逻辑无法正常循环。

修改方案

1. 添加格式字符串

在.data段中添加printf需要的格式字符串,用来输出三个64位统计值:

fmt_str: .asciz "%ld %ld %ld\n"

2. 修正统计逻辑

  • 每次读取字符后先判断是否是EOF(-1),是则退出循环。
  • 判断当前字符是否是单词分隔符(空格、换行、制表符等),以此更新iInWord的状态,正确统计单词数。
  • 遇到换行符时增加行数统计。

3. 正确实现打印逻辑

打印代码要放在输入处理完成后的代码块中,按照ARMv8调用约定传递参数:

  • x0 = 格式字符串fmt_str的地址
  • x1 = lLineCount的值
  • x2 = lWordCount的值
  • x3 = lCharCount的值
    然后调用printf。

完整修改后的代码

.section        .data
lLineCount:     .quad   0       # 行数统计
lWordCount:     .quad   0       # 单词数统计
lCharCount:     .quad   0       # 字符数统计
iInWord:        .quad   0       # 是否在单词中的标记:1=在单词内,0=不在
fmt_str:        .asciz  "%ld %ld %ld\n"  # printf格式字符串

        .section        .text
        .global        main

main:
        stp     x29, x30, [sp, -16]!  # 保存栈帧和返回地址
        mov     x29, sp

.L_loop:
        bl      getchar               # 读取一个字符,返回值存在x0
        cmp     x0, #-1               # 判断是否是EOF
        b.eq    .L_print_result       # 是EOF则跳转到打印结果

        # 统计字符数
        adrp    x1, lCharCount
        add     x1, x1, :lo12:lCharCount
        ldr     x2, [x1]
        add     x2, x2, #1
        str     x2, [x1]

        # 判断是否是换行符,统计行数
        cmp     x0, #'\n'
        b.ne    .L_check_word
        adrp    x1, lLineCount
        add     x1, x1, :lo12:lLineCount
        ldr     x2, [x1]
        add     x2, x2, #1
        str     x2, [x1]
        # 换行符是单词分隔符,标记不在单词内
        adrp    x1, iInWord
        add     x1, x1, :lo12:iInWord
        mov     x2, #0
        str     x2, [x1]
        b       .L_loop

.L_check_word:
        # 判断是否是单词分隔符(空格、制表符)
        cmp     x0, #' '
        b.eq    .L_out_of_word
        cmp     x0, #'\t'
        b.eq    .L_out_of_word
        # 不是分隔符,判断是否在单词内
        adrp    x1, iInWord
        add     x1, x1, :lo12:iInWord
        ldr     x2, [x1]
        cmp     x2, #0
        b.ne    .L_loop               # 已经在单词内,直接循环
        # 不在单词内,开始新单词,单词数+1
        adrp    x1, lWordCount
        add     x1, x1, :lo12:lWordCount
        ldr     x2, [x1]
        add     x2, x2, #1
        str     x2, [x1]
        # 标记进入单词内
        mov     x2, #1
        str     x2, [x1]
        b       .L_loop

.L_out_of_word:
        # 是分隔符,标记不在单词内
        adrp    x1, iInWord
        add     x1, x1, :lo12:iInWord
        mov     x2, #0
        str     x2, [x1]
        b       .L_loop

.L_print_result:
        # 加载格式字符串地址到x0
        adrp    x0, fmt_str
        add     x0, x0, :lo12:fmt_str
        # 加载行数到x1
        adrp    x1, lLineCount
        add     x1, x1, :lo12:lLineCount
        ldr     x1, [x1]
        # 加载单词数到x2
        adrp    x2, lWordCount
        add     x2, x2, :lo12:lWordCount
        ldr     x2, [x2]
        # 加载字符数到x3
        adrp    x3, lCharCount
        add     x3, x3, :lo12:lCharCount
        ldr     x3, [x3]
        # 调用printf
        bl      printf

        # 退出程序
        mov     x0, #0
        ldp     x29, x30, [sp], 16
        ret

说明

  • 打印逻辑放在.L_print_result块中,也就是输入处理完成(遇到EOF)之后,确保统计完成再输出。
  • 按照ARMv8的调用约定,正确传递printf的参数,x0是格式字符串,x1-x3对应三个统计值。
  • 修正了统计逻辑,现在可以正确区分单词、换行符,统计行、单词、字符数。

内容的提问来源于stack exchange,提问作者Rose Ben Ann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:40:19