Not a hard and fast rule but moving data around is easier today (than a floppy from one computer to another with the prom programmer on it). And particularly i if you have a bundled IDE that vendor likely uses the toolchains default format, but even if not elf and other similar formats are supported and you don't have to go the route of a raw binary or an ihex or srec. But it still depends on the tool that takes the "binary" and programs it into the ROM(/FLASH) on the MCU. Now I cheated to demonstrate the large file problem above, instead you have to do more work when it is not a ram only system. If you feel the need to have .data or desire to have .bss zeroed then you need to write or use a more complicated linker script that helps you out with the locations and boundaries. And that linker script is married to the bootstrap that uses linker generated information to perform those tasks. Basically a copy of .data needs to be preserved in non-volatile memory (ROM/FLASH) but it cant live there at runtime .data is read/write so ideally/typically you use the linker scripts language/magic to state that the .data read/write space is blah, and the flash space is boo at this address and this size so the bootstrap can copy from flash at that address for that amount of data to ram. And for .bss the linker script generates variables that we save into flash that tell the bootstrap to zero ram from this address to this address. So operating system defines the memory space, the linker script matches that if you want the program to work. The system designers or chip designers determine the address space for something embedded and the linker script matches that. The bootstrap is married to the linker script for that build and target.
Some folks will argue and is sometimes true that compiles don't generate assembly any more. Still the sane way to do it and you will find it more often than not, as in this case... The bootstrap makes an object which we can disassemble.
It's not "linked" so the address this disassembler uses is zero based, and you can see the call to notmain is incomplete, not yet linked. the compiler generated assembly for the C code
Now not shown but that object also contains information for the global variable xyz and its size. The linkers job is perhaps part of your confusion. It links the objects together such that the result will be sane or will work on the final destination (bare-metal or operating system).
I made this linker script so that you can see both .data and .bss moving around. The linker has filled in all of the .text into the 0x1000 address space and has patched in the call to notmain() as well as how to reach xyz. It has also allocated/defined the space for the xyz variable in the 0x2000 address space. And then to your next question or confusion. It is very much up to the tools that load the system, be it the operating system loading a program into memory to be run, or programming the flash of an MCU or programming the ram of some other embedded system (like a mouse for example which you might not know some of them the firmware is downloaded from the operating system and not all of it burned into a flash /lib/firmware or other locations).
1条答案
按热度按时间cedebl8k1#
一个特定的操作系统有一个特定的规则集,或者可能有多个规则集,规定兼容程序可以加载到哪里。为该平台制作的包括默认链接器脚本(想想gcc hello.c -o hello)的工具链符合这些规则。
例如,我决定为具有MMU的平台创建一个操作系统。因为它具有MMU,所以我可以创建操作系统,以便每个程序都看到相同的内容(虚拟)地址空间。所以我可以决定对于我的操作系统上的应用程序,内存空间从0x 00000000开始,但入口点必须是0x 00001000。支持的二进制文件格式是摩托罗拉s记录。
因此,以一个简单的程序和一个简单的链接器脚本为例
简单程序的反汇编
而“二进制”文件恰好是人类可读的:
您可能会注意到,也可能不会注意到,该地址确实是在描述对象所在位置的二进制文件中。
作为一个基于操作系统的程序,加载到内存中,我们不必玩太多的游戏与内存,我们可以假设一个单位的所有内存(读/写),所以如果有.数据,.bss等,它都可以 Package 在那里。
对于一个真实的的操作系统来说,二进制文件应该包含额外的信息,比如程序的大小。所以你可以搜索一下各种常见的文件格式,看看是怎么做到的,要么是一个简单的前面我需要这么多,要么是一个到多个单独定义的部分。是的,“二进制”不仅仅是操作码和数据,我想你明白了。
默认情况下,我使用的工具链输出elf格式的文件,但objcopy可以用于创建许多不同的格式,其中一种是原始内存映像(不包含任何地址/位置信息),其余的许多/大部分包含机器代码和数据,以及调试器/反汇编器的标签或数据块在内存空间中的地址等。
现在,当您提到嵌入式并使用ROM和RAM时,我假设您指的是裸机,例如微控制器,但即使你指的是启动一个x86或全尺寸ARM或任何相同的事情适用。在MCU的情况下,芯片设计师可能已经根据处理器的规则或他们自己的选择确定了存储器空间的规则。就像操作系统将规定规则一样。我们有一点作弊,因为我们今天使用的很多工具但是因为通用编译器是通用编译器并且更重要的是工具链本身适合于这种可移植性,我们可以使用这样的工具。理想情况下,使用交叉编译器意味着输出的机器代码不一定要在生成该输出机器代码的计算机上运行。重要的主要区别在于,我们希望控制链接和库,而不是在基于库的主机操作系统中进行链接,而是让我们控制,或者对于此工具链,我们有一个面向MCU的默认链接器脚本。假设我有一个基于ARM 7 TDMI的MCU,并且芯片设计者说我需要这样的二进制,使得ROM从地址0x 00000000开始并且具有一定的大小,并且RAM从0x 40000000开始并且具有一定的大小。作为ARM 7,处理器通过获取地址0x 00000000处的指令开始执行,芯片设计人员已将0x 00000000Map到罗
现在我的简单程序
这样链接
给出了它的分解
这将是一个完全有效的程序,虽然没有什么有趣的功能,但仍然是一个完全有效的程序。
首先也是最重要的一点是,如果您不输入out _start,工具链会发出警告,但仍然可以正常工作。(嗯,实际上那次没有发出警告,很有趣)。
现在你有加载问题。每个MCU是不同的,你如何加载它,什么工具是可用的和/或你使自己的工具。Ihex和srec是流行的prom程序员,你说一个单独的rom旁边的处理器和/或通孔MCU将得到插入prom程序员。原始二进制图像也工作,但可以很快得到大,如将显示在第二。如上所述,有.bss但没有.data,因此
40个字节。但如果我这样做是为了演示的目的,即使它不能正确工作:
与
给予
和
OUCH!0x 40000004字节,这是预期的,我要求一个内存映像,我在一个地址(机器码)定义了一些东西,在另一个地址(0x 40000000)定义了一些字节,所以原始内存映像必须是整个范围。
相反,您可以使用工具链生成的elf文件或ihex或srecord。
所有的信息,我需要的,但不是一个巨大的文件这么少的字节。
Not a hard and fast rule but moving data around is easier today (than a floppy from one computer to another with the prom programmer on it). And particularly i if you have a bundled IDE that vendor likely uses the toolchains default format, but even if not elf and other similar formats are supported and you don't have to go the route of a raw binary or an ihex or srec. But it still depends on the tool that takes the "binary" and programs it into the ROM(/FLASH) on the MCU.
Now I cheated to demonstrate the large file problem above, instead you have to do more work when it is not a ram only system. If you feel the need to have .data or desire to have .bss zeroed then you need to write or use a more complicated linker script that helps you out with the locations and boundaries. And that linker script is married to the bootstrap that uses linker generated information to perform those tasks. Basically a copy of .data needs to be preserved in non-volatile memory (ROM/FLASH) but it cant live there at runtime .data is read/write so ideally/typically you use the linker scripts language/magic to state that the .data read/write space is blah, and the flash space is boo at this address and this size so the bootstrap can copy from flash at that address for that amount of data to ram. And for .bss the linker script generates variables that we save into flash that tell the bootstrap to zero ram from this address to this address.
So operating system defines the memory space, the linker script matches that if you want the program to work. The system designers or chip designers determine the address space for something embedded and the linker script matches that. The bootstrap is married to the linker script for that build and target.
Edit
toolchain basics...
My bootstrap, main program and linker script
Some folks will argue and is sometimes true that compiles don't generate assembly any more. Still the sane way to do it and you will find it more often than not, as in this case...
The bootstrap makes an object which we can disassemble.
It's not "linked" so the address this disassembler uses is zero based, and you can see the call to notmain is incomplete, not yet linked.
the compiler generated assembly for the C code
that gets assembled into an object which we can also disassemble.
Now not shown but that object also contains information for the global variable xyz and its size.
The linkers job is perhaps part of your confusion. It links the objects together such that the result will be sane or will work on the final destination (bare-metal or operating system).
I made this linker script so that you can see both .data and .bss moving around. The linker has filled in all of the .text into the 0x1000 address space and has patched in the call to notmain() as well as how to reach xyz. It has also allocated/defined the space for the xyz variable in the 0x2000 address space.
And then to your next question or confusion. It is very much up to the tools that load the system, be it the operating system loading a program into memory to be run, or programming the flash of an MCU or programming the ram of some other embedded system (like a mouse for example which you might not know some of them the firmware is downloaded from the operating system and not all of it burned into a flash /lib/firmware or other locations).