Gcc 如何将main()重新定位到0x00000000?

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__

这是我程序的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__
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处,从而解决了我的问题。谢谢你的帮助!