Gcc 如何将main()重新定位到0x00000000?
这是我程序的nm转储Gcc 如何将main()重新定位到0x00000000?,gcc,assembly,ld,avr,Gcc,Assembly,Ld,Avr,这是我程序的nm转储 00000000 T __ctors_end 00000000 T __ctors_start 00000000 T __dtors_end 00000000 T __dtors_start 00000000 a __tmp_reg__ 00000000 T __trampolines_end 00000000 T __trampolines_start 00000000 T setup 00000001 a __zero_reg__ 0000003d a __SP_L__
00000000 T __ctors_end
00000000 T __ctors_start
00000000 T __dtors_end
00000000 T __dtors_start
00000000 a __tmp_reg__
00000000 T __trampolines_end
00000000 T __trampolines_start
00000000 T setup
00000001 a __zero_reg__
0000003d a __SP_L__
0000003e a __SP_H__
0000003f a __SREG__
00000072 T __vector_15
00000086 T main
000000a8 A __data_load_end
000000a8 A __data_load_start
000000a8 T _etext
00800100 D _edata
00800100 T _end
00810000 T __eeprom_end
该体系结构是AVR,我需要将main()恢复到0x00000000,以便运行此代码的芯片能够正确执行。它应该像链接器脚本一样简单,不是吗?我曾经为AVR编程,我知道更改
main()
条目的唯一方法是熔丝位。但是你可以把它放在FLASH的后面,作为引导加载程序。根据芯片主启动位置的不同,我不确定,但在AVR上,它应该类似于0x20
到0x100
这是因为在开始时有复位向量、寄存器和中断向量。
这种结构非常有用,一旦我有一个项目,我不能使用看门狗,所以触发重置的唯一方法是溢出
另外,我也读了你的评论。您不需要将256字节的0x00
放在某些寄存器(AVR寄存器分为SRAM和其他闪存)和中断向量的位置,因此如果您使用定时器或UART,并且代码从0x00
开始,那么这些寄存器的初始化将破坏您的代码
它是为了工作而设计的,我认为重新设计会破坏它。但是如果您真的想要这样做,您可以尝试添加
-Ttext=0x0000
此标志这可以根据您的需要编译它,但我不建议这样做。内存中的main()
位置无关紧要。只需将跳转
指令放到重置向量处的地址,或应用程序内存中的0x0000
。是否确实要main
位于0x00000000
?我看到的AVR文档说,第一次运行的代码将是一个引导加载程序,它从256B
到4KB
,然后跳转到主程序。0x00000000
是我需要的main()
at在二进制文件中,因为为了节省编程时间,我正在闪烁二进制文件以从256B开始。但是,谢谢你的观察。好的,谢谢你的澄清。通常情况下,写入闪存的文件格式(例如英特尔十六进制或S记录)会考虑目标地址,而不应考虑文件中的地址。听起来你是在直接创建一个二进制图像文件。如果当前文件的主地址从该文件中的256开始,那么前256个字节中有什么内容?在您的系统上编程256字节需要多少编程时间?这应该很快。我说的二进制是指编译器生成的实际字节码,它的格式是英特尔十六进制。很抱歉没有澄清这一点main()
在我的十六进制文件中不是从256B
开始的,因为我在芯片本身的256B
开始编程文件的第一个地址。因此,我需要将main()
从文件的第一个地址开始。就时间而言,这不是什么大问题,但对我来说,按我现在的方式编程更方便,而不是每次编译时都在文件的开头追加256字节0的。-Ttext=0x0000
不起作用,因为main()
不在文本部分的开头,setup()。但是,好吧。我对充分利用AVR
体系结构很感兴趣,请告诉我您认为我可以如何利用闪存的第一个256B
跳到main()
在它可能位于的任何地址。@GeorgeMorgan首先,我想问你有什么芯片,你在使用什么编译器。实际上,在禁用指向引导加载程序地址的保险丝后,我将跳转指令放在main()
0x000处,从而解决了我的问题。谢谢你的帮助!