我有以下宏来嵌入文件名中的二进制数据:
#define INCBIN(identifier, filename) \
asm(".pushsection .rodata\n" \
"\t.local " #identifier "_begin\n" \
"\t.type " #identifier "_begin, @object\n" \
"\t.align 16\n" #identifier "_begin:\n" \
"\t.incbin \"" filename "\"\n\n" \
\
"\t.local " #identifier "_end\n" \
"\t.type " #identifier "_end, @object\n" \
"\t.align 1\n" #identifier "_end:\n" \
"\t.byte 0\n" \
"\t.popsection\n"); \
\
extern std::byte const identifier##_begin[]; \
extern std::byte const identifier##_end[]我希望能够声明它是一个uint32_t而不是一个std::byte。这将要求该文件的整数倍数为4字节。对齐已由宏处理(对齐到16)。如果文件大小不好,我能触发编译时错误吗?也就是说,向程序集添加一些编译时断言。
发布于 2022-02-06 21:02:02
如果您只是在文件之后使用.p2align 2,那么无论.incbin组装到多少字节,它的总大小都将达到4个字节的倍数。(因为文件从对齐位置开始)。
如果您想要检查而不是pad,则可以在组装时使用汇编程序指令进行检查。显然不是在编译时正确,因为这只是将C++转换为asm,以便稍后提供给汇编程序。(在GCC中,这些步骤实际上是分开的,并不是同一个编译器过程的所有部分。但在其他实现中,逻辑上仍然是连续的。)
在同一个文件中,两个标签之间的距离是一个集合时间常数,您可以在气体表达式(如(b-a)&3 )中使用它。
如果您使用.rept -((b-a)&3),您将有一个0或负重复计数,后者是一个集合时错误,根据文件大小%4为非零。(有趣的事实: Linux内核在C中使用这样的技巧通过生成一个0或负大小的数组来进行静态断言)。
甚至更好的是,. 可以由 或其他GAS指令(如)控制(.rept会重复错误消息(b-a)%4次数,而如果大于零则只重复一次)。
.p2align 2
a:
.incbin "bin"
# .p2align 2
b:
.ifgt (b-a)&3 # true if remainder > 0
.error "asm static_assert failed: file size not a multiple of 4"
.endif$ echo xyz > bin # size 4
$ gcc -c foo.s
$ echo >> bin # size 5
$ gcc -c foo.s
foo.s: Assembler messages:
foo.s:9: Error: asm static_assert failed: file size not a multiple of 4用GNU汇编程序(GNU Binutils) 2.36.1进行测试
我将让您将其填充回您的内联asm宏中,并在.error字符串中使用文件名。
https://stackoverflow.com/questions/71011580
复制相似问题