在 NASM 中使用 istruc 时:“警告:尝试初始化 BSS 部分 '.bss' 中的内存:忽略 [-w+other]”

When using istruc in NASM: "warning: attempt to initialize memory in BSS section `.bss': ignored [-w+other]"

提问人:trxgnyp1 提问时间:8/30/2023 最后编辑:ecmtrxgnyp1 更新时间:8/31/2023 访问量:79

问:

在搜索此错误时,我发现了这个问题,但并不完全是我的问题。过了一会儿,我弄清楚了问题所在,并在该问题中发布了另一个答案,但听从@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]

问:为什么会出现此警告?为什么是四次?如何避免呢?

程序集 结构 编译器错误 警告 NASM

评论


答:

1赞 trxgnyp1 8/30/2023 #1

添加缺失修复了它,所以在@ecm回答并解释原因之前,我没有考虑太多错误。at ctx_t.b, resd 1

事实证明,通过自己不保留字节,汇编程序声明了一个零字节 N 次(成员的大小):Link

因此,在这种情况下,因为是一个 dword,它使用 .显然,该部分不是声明字节的正确位置(因为它是一个部分,不像,例如,它是)。.btimes 4 db 0.bssnobits.textprogbits

解决方案是为缺失的成员添加 ,或者将 移动到一个部分(显然替换 's)。resdistrucprogbitsresd

这就是为什么编译器不仅发出警告,而且发出 4 个警告(每个警告一个)的原因db 0)

2赞 ecm 8/31/2023 #2

以下是一些其他解决方案。首先,重现原始问题的测试用例(在一个可以按原样组装的文件中):

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 定义它是一致的。这是唯一需要更改代码的解决方案,而不仅仅是添加一些宏。nobitsbss_istrucbss_istrucistruc


%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.bssresb 1db 0nobits.bss

它还期望 mmacros 仅在 plain 或指令之后使用。如果要指定部分属性(例如,、等),则需要随后添加另一个指令,该指令仅命名部分名称而不命名属性。(无论如何,这是一个很好的形式,因为使用宏会警告你的最后一个指令是否包含属性。section .bsssegment .bssfollows=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 0resbtimesdb 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

接下来,对上述内容进行修订,使其工作,方法是对 .这是一个超级黑客解决方案,但如果您注意只使用这个技巧进行替换,它确实有效。(预计到达时间:稍作修改,以允许任何具有单个数字的工作。dbdb 0db


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 更安全。dbtimes 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

评论

1赞 trxgnyp1 8/31/2023
很有意思。我以为是预处理器指令。times
0赞 ecm 8/31/2023
@trxgnyp1 预处理器循环的相应构造是使用 和 指令实现的。%rep%endrep