"warning: section .bss: alignment 2**32 not representable" 在 GNU 汇编器中是什么意思?

What does "warning: section .bss: alignment 2**32 not representable" mean in GNU Assembler?

使用 MinGW-w64 附带的 GNU 汇编器版本汇编由我的编译器生成的 x86 汇编代码会产生以下警告:

E:/MinGW32/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/ld.exe: analogClockForWindows.exe: warning: section .bss: alignment 2**32 not representable

这是什么意思?最让我不解的是,汇编代码里根本就没有提到.bss
不知道有没有关系,但是CygWin自带的GNU Assembler的版本和自带的TDM-GCC 甚至都拒绝 assemble 我的代码,并给出大量错误消息。
我的编译器生成的汇编代码可在此处获得:https://github.com/FlatAssembler/ArithmeticExpressionCompiler/files/6446315/analogClockForWindows.s.zip

编辑:我只是使用 gcc -o analogClockForWindows analogClockForWindows.s 编译由 my compiler 生成的汇编代码。

更新:我认为这是触发该警告的最小示例:

.text
.comm   output,7360,32
.global _main
_main:
movl    [=12=], %eax
ret

这可能意味着您使用了 .align 32,它被解释为 .p2align(2 的幂)而不是 .balign(字节)。

在定位 GAS 时,切勿使用不明确的 .align 指令,它支持明确的指令。


在您的例子中,对齐出现在 .comm 的第 3 个参数中,以在 BSS 中定义一个全局变量。像 .align 一样,解释是依赖于目标的,当为 Windows 组装时,这意味着你要求它按 2**32(或 4GiB)对齐,ld不处理。

(当为 i386-elf-linux 进行汇编时,它意味着按 32 位对齐,2**5,按预期工作。)

the GAS manual 中所述:

When using ELF or (as a GNU extension) PE, the .comm directive takes an optional third argument. This is the desired alignment of the symbol, specified for ELF as a byte boundary (for example, an alignment of 16 means that the least significant 4 bits of the address should be zero), and for PE as a power of two (for example, an alignment of 5 means aligned to a 32-byte boundary).

The alignment must be an absolute expression, and it must be a power of two. If ld allocates uninitialized memory for the common symbol, it will use the alignment when placing the symbol.

If no alignment is specified, as will set the alignment to the largest power of two less than or equal to the size of the symbol, up to a maximum of 16 on ELF, or the default section alignment of 4 on PE

不幸的是,没有可移植的明确语法方式来使用它。您可以省略可选的第三个参数并使用默认对齐方式。

或者您可以改为使用 .bss 指令切换到 BSS 部分,并使用 .spacelabel:.

之后保留 space

或者只是不使用任何全局变量,并将结果留在 st0 如果你采取堆栈上的参数而不是全局变量。如果您在 x87 寄存器中 运行,您最多可以使用堆栈 space。或者您可以引用全局变量,但将定义留给其他编译单元(例如执行 input/output.)

的调用者

另外,result真的需要7360字节吗?您的编译器 (https://flatassembler.github.io/compiler.html) 只使用 [result],而不是 [result + reg]+ constant

https://sourceware.org/binutils/docs/as/Comm.html#Comm

When using ELF or (as a GNU extension) PE, the .comm directive takes an optional third argument. This is the desired alignment of the symbol, specified for ELF as a byte boundary (for example, an alignment of 16 means that the least significant 4 bits of the address should be zero), and for PE as a power of two (for example, an alignment of 5 means aligned to a 32-byte boundary).

ELF是Linux上使用的可执行格式,PE是Windows上使用的。所以对于 ELF(Linux),.comm output,7360,32 要求 output 对齐到 32 字节边界,这很好。但是对于 PE (Windows),相同的指令被解释为要求 2**32 字节对齐,这是不可能的。在 Windows 你应该写成 .comm output,7360,5.

我不知道为什么这些不同;可能是为了与其他不同的汇编程序兼容。

您可能需要在 Windows 和 Linux 之间向 select 的编译器添加一个标志,以便可以为每种情况输出正确的指令。