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
相关产品推荐
相关产品推荐

