AVR编译后SRAM数据段存储异常:初始化值与读取值不符
问题:SRAM数组预初始化值与实际读取值不一致(ATmega328P/Arduino环境)
你在ATmega328P的Arduino环境下用汇编代码预初始化SRAM数组,预期首元素为0x44(字符'D'),但实际读取到0x41(字符'A'),核心问题出在手动指定SRAM地址与Arduino的启动初始化流程冲突。
你的代码如下:
.data .org 0x0100 system_log: .space 20, 0x44 .byte 10,13,0 .text .org 0x4000 loop: rjmp loop print_buff: LDI XL, lo8(system_log) LDI XH, hi8(system_log) ;Z points to string message ld r0, X mov r18, r0 rjmp print_msg
原因分析
ATmega328P的SRAM起始地址是0x0100,但Arduino的启动代码会在程序运行前执行两项关键操作:
- 清除BSS段(未初始化全局变量的区域)
- 将Flash中存储的.data段初始化数据复制到SRAM对应地址
你手动用.org 0x0100强制把system_log放在SRAM起始位置,这个区域正好是Arduino启动代码的初始化操作范围,导致你预初始化的0x44被启动代码覆盖(0x41大概率是初始化过程中残留的临时值)。
解决方案
直接去掉.org 0x0100,让Arduino的链接脚本自动分配SRAM地址,避免与系统初始化流程冲突:
修改后的代码:
.data system_log: .space 20, 0x44 .byte 10,13,0 .text .org 0x4000 loop: rjmp loop print_buff: LDI XL, lo8(system_log) LDI XH, hi8(system_log) ld r0, X mov r18, r0 rjmp print_msg
验证逻辑
去掉手动地址指定后,链接器会按照Arduino的内存布局规则,将system_log分配到SRAM中未被系统初始化操作覆盖的区域,此时预初始化的0x44会被正确从Flash复制到SRAM,读取时就能得到预期的字符'D'。
内容的提问来源于stack exchange,提问作者user25562504
相关产品推荐
相关产品推荐

