C++ ARM二进制大小
我正在使用ARM GCC noneabi编译器、c/c++编写MCU,如STM32F4**和STM32F0**,并发现了有趣的模式 如果我构建一些*.bin文件,它的大小总是可以被4整除 我想这可能是因为MCU是32位(=4字节)。因此,bin_大小%4==0。我尝试过一些“黑客”;例如,将某些字节数组放大1,但二进制大小始终相同。当我进一步放大数组时,二进制大小会更大,但也可以被4整除C++ ARM二进制大小,c++,binary,arm,stm32,bin,C++,Binary,Arm,Stm32,Bin,我正在使用ARM GCC noneabi编译器、c/c++编写MCU,如STM32F4**和STM32F0**,并发现了有趣的模式 如果我构建一些*.bin文件,它的大小总是可以被4整除 我想这可能是因为MCU是32位(=4字节)。因此,bin_大小%4==0。我尝试过一些“黑客”;例如,将某些字节数组放大1,但二进制大小始终相同。当我进一步放大数组时,二进制大小会更大,但也可以被4整除 我可以把这个效应看作公理吗?< /P> 或者在某些情况下,这不起作用?例如,是否可能以某种方式将32位STM
我可以把这个效应看作公理吗?< /P>
或者在某些情况下,这不起作用?例如,是否可能以某种方式将32位STM32 MCU切换到16位模式?或者可以使用其他编译器创建不可被4整除的二进制文件?可以创建任意大小的二进制文件,4字节对齐只是一个方便的问题。每个人都是这样做的,每个人都期待着 在链接器脚本文件中强制对齐。如果您查看项目的
*.ld
文件,您会发现有很多
. = ALIGN(4);
声明。它们指示链接器将当前输出地址提升到可被4整除的值
因此,我创建了一个空项目,并从链接器脚本中删除了大部分ALIGN
行:
ENTRY(Reset_Handler)
__stack = 0x20014000;
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 80K
}
SECTIONS
{
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
.text :
{
*(.text)
*(.text*)
} >FLASH
.rodata :
{
*(.rodata)
*(.rodata*)
} >FLASH
_sidata = LOADADDR(.data);
.data :
{
_sdata = .;
*(.data)
*(.data*)
_edata = .;
} >RAM AT> FLASH
.bss :
{
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
_ebss = .;
} >RAM
}
最小程序:
void Reset_Handler(void) {
while(1)
;
}
编译并将其与-nostartfiles-nodefaultlibs-nostlib
链接,以省去所有标准库内容。结果是
arm-none-eabi-size --format=berkeley "unaligned.elf"
text data bss dec hex filename
320 0 0 320 140 unaligned.elf
可以被四整除的。然后我添加了一个char变量,并用它做了一些事情:
volatile char c = 0x42;
void Reset_Handler(void) {
while(1)
c+=1;
}
导致
Invoking: Cross ARM GNU Print Size
arm-none-eabi-size --format=berkeley "unaligned.elf"
text data bss dec hex filename
336 1 0 337 151 unaligned.elf
Finished building: unaligned.siz
指令与16位对齐。
基于Cortex-M的MCU(如STM32系列)使用Thumb2指令集,它是16位和32位指令的混合。事实证明,我们的第一个程序恰好有一个长度可以被4整除。我添加了一条nop
指令
void Reset_Handler(void) {
asm("nop");
while(1)
;
}
与原始文件相比,文件大小增加了两个字节:
Invoking: Cross ARM GNU Print Size
arm-none-eabi-size --format=berkeley "unaligned.elf"
text data bss dec hex filename
322 0 0 322 142 unaligned.elf
Finished building: unaligned.siz
例如,是否可能以某种方式将32位STM32 MCU切换到16位模式
有一种16位模式,但您可能不完全理解这意味着什么。要用谷歌搜索它,你需要搜索“手臂拇指”。这很可能会导致*bin文件是2字节的倍数
然而,“32位模式”和“16位模式”通常指指针或寄存器大小,而不是指令大小。例如,AMD x64指令集可称为“64位模式”,即使其指令长度可变。有些x64指令只有一个字节。你到底为什么希望二进制文件的大小不是4的倍数???你的目标是什么?编译器可能正在填充您的结构以确保干净的内存访问。如果你想打破这个,我不知道你希望达到什么。打开文件,在末尾添加一个字节,关闭它,你可以有一个奇数长度的文件,然后看看有多少工具在你尝试使用它时会打破…太好了,你的答案完全涵盖了我需要知道的所有问题!我已经打开了我的*.ld文件,并且有在每个部分对齐(4)。这可能就是为什么我的二进制文件大小总是可以被4整除的原因。我问这个问题是因为我有自己的引导加载程序,它能够将新的二进制文件闪存到MCU,我认为“可被4整除”规则是新的二进制文件必须通过的规则之一,还有CRC检查等等。现在我知道这并不容易。