应用程序启动代码如下所示:
CPU 8086
_start:
cld
mov ax, ds
dec ax
mov es, ax
mov ax, [es:3]
cmp ax, word (_endbss + 768) / 16
jae .mem
; Code would be here to emit an out of memory error
.mem:
mov ax, 4C00h
int 21h
section .bss
_bss:
big_array resb 16384
_endbss:
它应该做什么?检查我们是否真的有足够的 RAM 来运行该程序。
它实际上在做什么?不是组装。
总体思路是我们需要很多 RAM,所以我们在初始段和其上方的 slab 中设置了 Code + BSS + Stack(它本身将超过 64K,因此将其放在堆栈下方是没有意义的。)。我确信汇编程序应该能够做到这一点,但我不知道要输入什么才能使其工作。
我如何得到要组装成最确定的常量的表达式(_endbss + 768) / 16
?我真的不想在运行时弄清楚它。
不幸的是, NASM 的
-f bin
工作原理与 NASM 内置的简单链接器类似。它不会覆盖通常的规则,即符号地址上的任何数学运算都必须可以用重定位条目表示,并且在汇编时(仅在链接时)是未知的。但是您可能仍然需要单独的部分,以便
resb
可以进入.bss
而不是组装到输出文件中的字节。您可以将两个部分的长度相加,前提是没有用于部分之间对齐的填充。(
section .bss align=1
我认为,如果这不是默认设置,您可以使用来实现这一点。)因此,我们_endtext
在的最后一个字节后添加一个标签.text
,有问题的指令变为:列出(
nasm -l /dev/stdout -f bin foo.asm
)一个工作示例:在实际的输出文件中
foo
,mov ax, _endbss
组装为b8 1c 40
(不像b8 00 40
清单中显示为占位符),所以1c 40
(小端)=0x401c
是完整地址的偏移部分,也是您想要_endbss
评估的内容。立即比较是小端字节序,
31 04
即0x0431
。将该
_endbss
值代入表达式中检查结果:(0x401c + 768) / 16
向下四舍五入为 1073,即0x431
我的表达式得到的值cmp
。我还没有对
times x db 1
.ext 或非2的幂.bss
大小的额外内容进行过广泛的测试,以确保在下一个大小之间的截止点处没有偏差,或者在下一个级别的对齐填充的截止点处没有偏差。