这将是非常具体的,但我很好奇。 我有一个 A.asm 文件和一个 B.asm 文件。
在A.asm中有:
global nodeNum
section .data
; reading consts
cmdNum equ 9
cmdSize equ 5
; tree consts
nodeNum equ 8
现在,在 B.asm 中:
extern nodeNum
section .bss
t1 resb 1
t2 resb 5*nodeNum
treevptr resd 1
组装此代码会出现“尝试在 BSS 空间中保留非常量数量”错误。
我的问题是:
equ
将常数与标签关联起来,那么为什么会出现这个错误呢?t1 resb 1
t2 resb (1*nodeNum + 1*nodeNum)
treevptr resd 1
它组装没有错误,但
nodeNum
为0,所以t1+1
变得与treevptr
相同。
为什么它在这里组装而不是在前一种情况下组装?
我也遇到了类似的问题。 我使用带有 %define 指令的预处理器:
%定义 BUFFLEN1 500
...
.bss 部分
我的缓冲区:resb BUFFLEN1
符号“地址”(在本例中实际上只是一个值)
nodeNum
只是一个链接时间常数,而不是汇编时间。但 NASM 为此需要一个汇编时间常量,因为对于从一个 .asm
文件生成的内容,布局需要固定1。
您应该
%include
您的equ
定义,而不是尝试使用链接器。(也许将常量移动到单独的.asm
或.h
,其中只有equ
和%define
内容,以便您可以包含它在多个其他文件中。)
这也将让 NASM 将
add ecx, nodeNum
等内容优化为 3 字节 add r/m32, imm8
而不是 6 字节 add r/m32, imm32
:当它看不到常量的实际数值时,它会留下最大空间因为小数可以填入很多位,但大数不能填入太少的位。 (此外,extern
符号通常是32或64位值的实际地址。)
脚注 1:可能没有允许链接器扩展可变数量的零的重定位类型。如果有 ELF
.o
文件,NASM 不支持。如果两个符号定义在同一个 .asm
中(例如,在您想要执行的操作的任一侧),NASM 会将它们之间的距离视为汇编时间常数,例如对于诸如 mov eax, foo - bar
之类的东西来填充数值作为汇编时间,或者众所周知的 times 510-($-$$) db 0
,它需要知道已经将多少字节发送到当前部分,以便它可以填充到 510 字节。