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

《圣诞十二天》GNU汇编程序段错误问题求助

《圣诞十二天》汇编程序崩溃问题排查与修复

崩溃原因分析

  1. 循环条件逻辑倒置:.loop_gift中的cmpq %r8, %rcx配合jg .next_day逻辑错误,原本应在礼物计数器%r8超过当天数%rcx时跳转至下一天,但当前判断是当天数大于礼物计数器就跳转,导致首日仅输出intro后直接进入下一天流程,后续寄存器被printf破坏后逻辑彻底混乱。
  2. 数组基地址加载错误:movq lines(%rip), %rdx取的是lines数组第一个元素(str01的地址),而非数组本身的基地址,后续通过(%rdx, %r9, 8)索引时会访问错误内存地址,触发段错误。
  3. 寄存器未遵循ABI规则:x86-64 SystemV ABI中,printf、putchar会破坏%rcx、%rdx、%r8-%r11等调用者保存寄存器,程序直接用这些寄存器存储计数器,调用函数后值被覆盖,导致循环逻辑失控。

修复方案与代码

修复点说明

  • 将天数计数器移至%rbx、礼物计数器移至%r12(二者为被调用者保存寄存器,函数调用不会破坏其值)。
  • 用lea lines(%rip), %rdx正确获取lines数组的基地址。
  • 修正.loop_gift中的循环判断条件,改为cmpq %rbx, %r12,当礼物计数器超过天数时跳转至下一天。
  • 调整"And"的打印逻辑,确保仅在非首日的最后一个礼物前输出。

修复后的完整代码

.globl main

.section .rodata
intro: .string "On day %ld of Christmas my true love sent to me\n"
and_s: .string "and "

str01: .string "%ld partridge in a pear tree\n"
str02: .string "%ld turtle doves\n"
str03: .string "%ld french hens\n"
str04: .string "%ld calling birds\n"
str05: .string "%ld gold rings\n"
str06: .string "%ld geese a-laying\n"
str07: .string "%ld swans a-swimming\n"
str08: .string "%ld maids a-milking\n"
str09: .string "%ld ladies dancing\n"
str10: .string "%ld lords a-leaping\n"
str11: .string "%ld pipers piping\n"
str12: .string "%ld drummers drumming\n"

lines:
    .quad str01, str02, str03, str04, str05, str06
    .quad str07, str08, str09, str10, str11, str12

.section .text
main:
    pushq %rbp
    movq %rsp, %rbp
    pushq %rbx        # 保存被调用者保存寄存器
    pushq %r12

    movq $1, %rbx     # 天数计数器(1-12),用%rbx避免被printf破坏
    lea lines(%rip), %rdx  # 正确加载lines数组的基地址

.loop_day:
    movq $intro, %rdi
    movq %rbx, %rsi
    call printf

    movq $1, %r12     # 礼物计数器(1-当天数),用%r12避免被破坏
.loop_gift:
    cmpq %rbx, %r12   # 判断礼物计数器是否超过天数
    jg .next_day      # 超过则进入下一天

    # 判断是否需要打印"and":非首日,且是最后一个礼物(r12 == rbx)
    cmpq $1, %rbx
    je .print_gift
    cmpq %rbx, %r12
    jne .print_gift

    # 打印"and "
    movq $and_s, %rdi
    call printf

.print_gift:
    leaq -1(%r12), %r9        # 计算索引(r12-1)
    movq (%rdx, %r9, 8), %rdi # 从数组中取对应字符串地址
    movq %r12, %rsi
    call printf

    incq %r12
    jmp .loop_gift

.next_day:
    movq $10, %rdi
    call putchar
    incq %rbx
    cmpq $13, %rbx    # 判断是否完成12天(1到12,所以比较13)
    jne .loop_day

    popq %r12         # 恢复寄存器
    popq %rbx
    leave
    ret

编译运行验证

使用原命令编译:

gcc -no-pie 12daysofxmas.s -o 12d

执行./12d即可正常输出完整的《圣诞十二天》歌词,无段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:35:14