提问人:trxgnyp1 提问时间:8/30/2023 最后编辑:ecmtrxgnyp1 更新时间:8/31/2023 访问量:79
在 NASM 中使用 istruc 时:“警告:尝试初始化 BSS 部分 '.bss' 中的内存:忽略 [-w+other]”
When using istruc in NASM: "warning: attempt to initialize memory in BSS section `.bss': ignored [-w+other]"
问:
在搜索此错误时,我发现了这个问题,但并不完全是我的问题。过了一会儿,我弄清楚了问题所在,并在该问题中发布了另一个答案,但听从@ecm的建议,我决定提出一个不同的问题。
我的问题是,前段时间我声明了这样的 nasm(请注意,没有 .b
):struc
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.c: resd 1
endstruc
过了一段时间,我添加了一个成员:.b
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
但是忘了在另一个文件中编辑结构的实际使用情况:istruc
section .bss
first_ctx:
istruc ctx_t
at ctx_t.next, resd 1
at ctx_t.prev, resd 1
at ctx_t.a, resd 1
; Missing b!
at ctx_t.c, resd 1
iend
汇编程序给了我这些警告(都在线上):ctx_t.c
src/file.asm:8: warning: attempt to initialize memory in BSS section `.bss': ignored [-w+other]
src/file.asm:8: warning: attempt to initialize memory in BSS section `.bss': ignored [-w+other]
src/file.asm:8: warning: attempt to initialize memory in BSS section `.bss': ignored [-w+other]
src/file.asm:8: warning: attempt to initialize memory in BSS section `.bss': ignored [-w+other]
问:为什么会出现此警告?为什么是四次?如何避免呢?
答:
添加缺失修复了它,所以在@ecm回答并解释原因之前,我没有考虑太多错误。at ctx_t.b, resd 1
事实证明,通过自己不保留字节,汇编程序声明了一个零字节 N 次(成员的大小):Link。
因此,在这种情况下,因为是一个 dword,它使用 .显然,该部分不是声明字节的正确位置(因为它是一个部分,不像,例如,它是)。.b
times 4 db 0
.bss
nobits
.text
progbits
解决方案是为缺失的成员添加 ,或者将 移动到一个部分(显然替换 's)。resd
istruc
progbits
resd
这就是为什么编译器不仅发出警告,而且发出 4 个警告(每个警告一个)的原因db 0
)
以下是一些其他解决方案。首先,重现原始问题的测试用例(在一个可以按原样组装的文件中):
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
section .bss
first_ctx:
istruc ctx_t
at ctx_t.next, resd 1
at ctx_t.prev, resd 1
at ctx_t.a, resd 1
; Missing b!
at ctx_t.c, resd 1
iend
resb 16
然后,我的第一个解决方案。我们使用单独的多行宏 (mmacros),专门用于 sections、named 和 friends。(mmacro 本身只是 NASM 的精确副本,但在这里沿其他两个 mmacro 定义它是一致的。这是唯一需要更改代码的解决方案,而不仅仅是添加一些宏。nobits
bss_istruc
bss_istruc
istruc
%imacro bss_istruc 1.nolist
%push
%define %$strucname %1
%$strucstart:
%endmacro
%imacro bss_at 1-2+.nolist
%defstr %$member %1
%substr %$member1 %$member 1
%ifidn %$member1, '.'
resb (%$strucname%1-%$strucname)-($-%$strucstart)
%else
resb (%1-%$strucname)-($-%$strucstart)
%endif
%2
%endmacro
%imacro bss_iend 0.nolist
resb %{$strucname}_size-($-%$strucstart)
%pop
%endmacro
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
section .bss
first_ctx:
bss_istruc ctx_t
bss_at ctx_t.next, resd 1
bss_at ctx_t.prev, resd 1
bss_at ctx_t.a, resd 1
; Missing b!
bss_at ctx_t.c, resd 1
bss_iend
resb 16
接下来,我的第二个解决方案。我们取消定义 NASM 的原始和朋友,并将它们替换为 mmacros,这些 mmacros 检查该部分、按名称,并在检测到该部分时使用,否则。显然,如果您使用命名的部分以外的部分,则必须修改检测以使其正常工作。istruc
.bss
resb 1
db 0
nobits
.bss
它还期望 mmacros 仅在 plain 或指令之后使用。如果要指定部分属性(例如,、等),则需要随后添加另一个指令,该指令仅命名部分名称而不命名属性。(无论如何,这是一个很好的形式,因为使用宏会警告你的最后一个指令是否包含属性。section .bss
segment .bss
follows=
align=
section
__SECT__
section
%unimacro istruc 1.nolist
%unimacro at 1-2+.nolist
%unimacro iend 0.nolist
%imacro istruc 1.nolist
%push
%define %$strucname %1
%$strucstart:
%ifidni __SECT__, [section .bss]
%define %$reservespace resb 1
%elifidni __SECT__, [segment .bss]
%define %$reservespace resb 1
%else
%define %$reservespace db 0
%endif
%endmacro
%imacro at 1-2+.nolist
%defstr %$member %1
%substr %$member1 %$member 1
%ifidn %$member1, '.'
times (%$strucname%1-%$strucname)-($-%$strucstart) %$reservespace
%else
times (%1-%$strucname)-($-%$strucstart) %$reservespace
%endif
%2
%endmacro
%imacro iend 0.nolist
times %{$strucname}_size-($-%$strucstart) %$reservespace
%pop
%endmacro
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
section .bss
first_ctx:
istruc ctx_t
at ctx_t.next, resd 1
at ctx_t.prev, resd 1
at ctx_t.a, resd 1
; Missing b!
at ctx_t.c, resd 1
iend
resb 16
接下来,一个不起作用的解决方案。这个想法是用一个宏来代替 mmacros 中的使用,该宏将扩展到许多指令。这不起作用,因为是汇编程序指令,而不是预处理器指令,因此永远不会被评估为 mmacro。这里转载给后人。db 0
resb
times
db 0
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
section .bss
first_ctx:
%imacro resb_for_every 1-*.nolist
%rep %0
%ifstr %1
%strlen %%length %1
resb %%length
%else
resb 1
%endif
%rotate 1
%endrep
%endmacro
%idefine db resb_for_every
istruc ctx_t
at ctx_t.next, resd 1
at ctx_t.prev, resd 1
at ctx_t.a, resd 1
; Missing b!
at ctx_t.c, resd 1
iend
%undef db
resb 16
接下来,对上述内容进行修订,使其工作,方法是仅对 .这是一个超级黑客解决方案,但如果您注意只使用这个技巧进行替换,它确实有效。(预计到达时间:稍作修改,以允许任何具有单个数字的工作。db
db 0
db
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
section .bss
first_ctx:
%idefine db resb 1 + 0 *
istruc ctx_t
at ctx_t.next, resd 1
at ctx_t.prev, resd 1
at ctx_t.a, resd 1
; Missing b!
at ctx_t.c, resd 1
iend
%undef db
resb 16
最后,对非工作解决方案的另一种看法:我们用一个特殊的 mmacro 代替指令,而不是指令。这个 mmacro 将检查其参数末尾的字符串,使其比之前的 hack 更安全。db
times
db 0
struc ctx_t
.next: resd 1
.prev: resd 1
.a: resd 1
.b: resd 1
.c: resd 1
endstruc
section .bss
first_ctx:
%imacro times_resb 1+.nolist
%defstr %%our_string %1
%strlen %%our_string_length %%our_string
%substr %%our_db_0 %%our_string %%our_string_length + 1 - 5,-1
%ifidni %%our_db_0, " db 0"
%substr %%our_number_string %%our_string 1,-6
%deftok %%our_number_token %%our_number_string
resb %%our_number_token
%else
%error Unexpected use of times_resb macro: %%our_string %%our_db_0
%endif
%endmacro
%idefine times times_resb
istruc ctx_t
at ctx_t.next, resd 1
at ctx_t.prev, resd 1
at ctx_t.a, resd 1
; Missing b!
at ctx_t.c, resd 1
iend
%undef times
resb 16
评论
times
%rep
%endrep
评论