我有以下宏來嵌入檔案名中的二進制資料:
#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[]
我希望能夠聲稱它是 anuint32_t而不是std::byte. 這將要求檔案具有 4 個位元組的整數倍。對齊已經由宏處理(對齊到 16)。如果檔案大小不正確,我可以觸發編譯時錯誤嗎?也就是說,向程式集添加一些編譯時斷言。
uj5u.com熱心網友回復:
如果您只是.p2align 2在檔案之后,它會將總大小四舍五入到 4 位元組的倍數,而不管.incbin組裝到多少位元組。(因為檔案開始于對齊的位置)。
如果您想檢查而不是 pad,則可以在匯編時使用匯編器指令進行檢查。顯然不是在編譯時正確的,因為這只是將 C 轉換為 asm 以便稍后提供給匯編器。(在 GCC 中,這些步驟實際上是獨立的,并不是同一個編譯器行程的所有部分。但在其他實作中邏輯上仍然是連續的。)
同一檔案中兩個標簽之間的距離是一個匯編時常數,您可以在 GAS 運算式中使用,例如(b-a)&3.
如果你使用.rept -((b-a)&3),你會有一個 0 或負的重復計數,后者是一個匯編時錯誤,根據檔案大小 % 4 是非零的。(有趣的事實:Linux 內核在 C 中使用類似的技巧通過生成一個大小為 0 或負數的陣列來執行靜態斷言)。
或者更好的是,.error可以由.rept其他 GAS 指令控制,例如.ifgt. (.rept將重復錯誤訊息(b-a)%4次數,而 if-greater-than-zero 僅重復一次。)
.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://www.uj5u.com/yidong/424430.html
