AVR汇编:如何从程序存储器加载空终止字符串入栈并反转写入数据存储器?
AVR汇编:加载Flash字符串压栈并反转写入SRAM
1. 从程序存储器加载空终止字符串并压栈
AVR的程序存储器(Flash)需通过LPM指令读取。空终止字符串以0x00结尾,我们逐个加载字节,非终止符则压入栈,同时记录字符串长度(方便后续反转写入)。
代码片段
; 在Flash中定义空终止字符串 .cseg my_str: .db "Hello World", 0x00 ; 寄存器定义 .def str_len = r17 ; 存储字符串长度 .def temp_byte = r16 ; 临时存储读取的字节 ; 初始化Z寄存器指向Flash字符串起始地址 ldi ZH, high(my_str << 1) ; Flash是16位字寻址,字节地址需左移1位 ldi ZL, low(my_str << 1) clr str_len ; 初始化长度计数器 load_and_push: lpm temp_byte, Z+ ; 读Flash字节到temp_byte,Z自增指向下一字节 cpi temp_byte, 0x00 ; 检查是否为空终止符 breq push_done ; 是则退出压栈循环 push temp_byte ; 非终止符压入栈 inc str_len ; 长度计数器+1 rjmp load_and_push push_done:
2. 将反转后的字符串写入数据存储器(SRAM)
栈是后进先出结构,弹出的字节即为原字符串的逆序。我们用X寄存器指向SRAM目标地址,按长度计数器循环弹出并写入,最后添加空终止符。
完整续接代码
; 初始化X寄存器指向SRAM目标起始地址(示例:0x0100) ldi XH, high(0x0100) ldi XL, low(0x0100) reverse_and_store: cpi str_len, 0x00 ; 检查是否已处理完所有字符 breq store_done pop temp_byte ; 弹出栈顶字节(逆序字符) st X+, temp_byte ; 写入SRAM,X自增指向下一地址 dec str_len ; 长度计数器-1 rjmp reverse_and_store store_done: st X, 0x00 ; 在反转字符串末尾添加空终止符 ; 程序终止(原地循环) end_loop: rjmp end_loop
关键细节说明
- Flash地址处理:AVR Flash采用16位字寻址,而
LPM按字节读取,因此字符串的字节地址需左移1位转换为字地址,才能让Z寄存器正确指向目标字节。 - 栈操作:
PUSH指令将寄存器值存入栈指针(SP)指向的SRAM地址,随后SP减1;POP指令从SP+1地址读取值到寄存器,随后SP加1,天然适配逆序需求。 - SRAM地址选择:需确保目标地址在当前AVR芯片的SRAM范围内,例如ATmega328P的SRAM范围是
0x0060到0x08FF,避免越界。
内容的提问来源于stack exchange,提问作者Trung Thành Đỗ
相关产品推荐
相关产品推荐

