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

ARM汇编编译报错symbol .data is in a different section 求助

ARM汇编编译错误排查与程序修复

问题背景

在树莓派4上使用GNU工具编译ARM汇编程序时,出现编译错误:Error: symbol .data is in a different section。程序预期功能为:生成100个1-6的随机数并存储,统计并打印连续重复序列(run)的总数及每个run的长度。

编译错误原因

错误直接来自print_roll_loop中的cmp r1, #rolls+400语句:

  • ARM架构的立即数指令(如cmp的#操作数)仅支持有限范围的立即数(由8位值循环移位生成),无法直接引用跨section的符号地址偏移。rolls属于.data段,而当前代码位于.text段,汇编器无法将rolls+400解析为合法立即数,因此抛出"symbol in different section"错误。

程序隐藏逻辑问题

除编译错误外,代码还存在多处逻辑bug,导致即使编译通过也无法正常工作:

  • 随机数生成错误:每次循环调用srand,会导致生成的随机数完全相同;且未对rand()结果取模,无法得到1-6的范围。
  • 数组定义错误:rolls: .word 100仅定义了一个值为100的字,而非100个整数的数组空间。
  • printf参数错误:打印单个骰子值时未传入格式字符串,会导致程序崩溃。
  • run计数循环条件错误:用run计数r4判断循环结束,与实际需要比较的相邻元素次数无关,会导致循环提前或延后终止。
  • 最后一个run未处理:循环结束后未统计最后一段连续序列。

完整修复方案

1. 修复编译错误

将直接引用跨section符号的立即数比较,改为先加载地址到寄存器再比较:

@ 替换原print_roll_loop中的cmp逻辑
ldr r2, =rolls+400  @ 加载数组结束地址(100个整数×4字节)
cmp r1, r2
bhs print_total_runs  @ 当指针到达或超出结束地址时退出

2. 修复数组定义

在.data段分配100个整数的空间:

rolls: .space 400    @ 100×4字节,用于存储100个骰子结果

3. 修复随机数生成逻辑

  • 在程序开头仅调用一次srand初始化种子(用系统时间)
  • 对rand()结果取模6,得到0-5后加1转为1-6
@ main函数开头添加随机数种子初始化
main:
push {lr}
bl time        @ 获取系统时间作为种子
mov r1, #0     @ time参数为NULL
bl srand       @ 仅初始化一次
pop {lr}

@ 修改roll_dice_loop中的随机数生成逻辑
roll_dice_loop:
bl rand        @ 生成随机数
mov r1, #6
bl __aeabi_idivmod  @ r0 = rand() % 6,r1 = rand() /6
add r0, r0, #1  @ 转为1-6
str r0, [r3], #4
subs r2, r2, #1
bne roll_dice_loop

4. 修复printf参数错误

在.rodata段添加骰子值的格式字符串,调用printf时传入正确参数:

@ .rodata段新增
die_format: .asciz "%d"

@ 修改print_roll_loop_next中的打印逻辑
print_roll_loop_next:
ldr r2, [r1], #4
ldr r0, =die_format
mov r1, r2
bl printf
ldr r0, =newline
bl printf

5. 修复run计数逻辑

  • 用数组指针判断循环是否到达倒数第二个元素(只需比较99次相邻元素)
  • 循环结束后处理最后一段run的统计与打印
@ 修改count_runs的循环条件
count_runs_loop:
ldr r0, [r3]
ldr r1, [r3, #4]
cmp r0, r1
beq increment_run

@ 打印当前run长度并重置
push {r0, r1}
mov r0, r5
ldr r1, =run_length
bl printf
pop {r0, r1}
mov r5, #1
add r4, r4, #1

increment_run:
add r3, r3, #4
ldr r2, =rolls+396  @ 倒数第二个元素的地址(99×4)
cmp r3, r2
bne count_runs_loop

@ 处理最后一个run
push {r0, r1}
mov r0, r5
ldr r1, =run_length
bl printf
pop {r0, r1}
add r4, r4, #1

修复后的完整代码

.section .data
rolls: .space 400    @ 存储100个骰子结果的数组
newline: .asciz "\n"

.section .rodata
die_format: .asciz "%d"
run_length: .asciz "Run length: %d\n"
total_runs: .asciz "Total number of runs: %d\n"

.section .text
.global main

@ 生成100个1-6的随机数并存储到数组
roll_dice:
push    {lr}
ldr     r3, =rolls
mov     r2, #100
roll_dice_loop:
bl      rand
mov     r1, #6
bl      __aeabi_idivmod
add     r0, r0, #1
str     r0, [r3], #4
subs    r2, r2, #1
bne     roll_dice_loop
pop     {pc}

@ 统计并打印连续重复序列的数量和长度
count_runs:
push    {lr}
ldr     r3, =rolls
mov     r4, #0      @ 总run数
mov     r5, #1      @ 当前run长度
count_runs_loop:
ldr     r0, [r3]
ldr     r1, [r3, #4]
cmp     r0, r1
beq     increment_run

@ 当前run结束,打印长度并重置
push    {r0, r1}
mov     r0, r5
ldr     r1, =run_length
bl      printf
pop     {r0, r1}
mov     r5, #1
add     r4, r4, #1

increment_run:
add     r3, r3, #4
add     r5, r5, #1
ldr     r2, =rolls+396
cmp     r3, r2
bne     count_runs_loop

@ 处理最后一个run
push    {r0, r1}
mov     r0, r5
ldr     r1, =run_length
bl      printf
pop     {r0, r1}
add     r4, r4, #1

@ 打印总run数
mov     r0, r4
ldr     r1, =total_runs
bl      printf
pop     {pc}

main:
@ 初始化随机数种子
push {lr}
bl time
mov r1, #0
bl srand
pop {lr}

bl roll_dice

@ 打印所有骰子结果
print_roll_loop:
ldr     r1, =rolls
print_roll_loop_next:
ldr r2, [r1], #4
ldr r0, =die_format
mov r1, r2
bl printf
ldr r0, =newline
bl printf
ldr r2, =rolls+400
cmp r1, r2
bhs print_total_runs
b print_roll_loop_next

print_total_runs:
bl count_runs

mov     r0, #0
bx      lr

编译运行

执行以下命令编译并运行:

gcc -o dice_runs dice_runs.s
./dice_runs

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:57:03