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

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的启动代码会在程序运行前执行两项关键操作:

  1. 清除BSS段(未初始化全局变量的区域)
  2. 将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:21:01