使用 times 和 align NASM 指令将指令放置在复位向量指向的地址中

Placing an instruction in the address pointed by the reset vector using times and align NASM directives

我一直在思考下面的汇编代码(NASM IA-32):

ORG 0xFF000 ; This is (1MB - 4KB) 0x100000 - 0x1000=0xFF000.
USE16 ;produce 16bit code
code_size EQU (end -init_16) ; calculates code length

times (4096-code_size) db 0x90 ; fills the rest of the memory with NOP's
init_16:
    cli ;disables interrupts (not really necessary, just an example)
    jmp init_16 ;infinite loop
align 16
end :

这只是一个例子。这个想法是我们在实模式下有一个 IA-32 处理器。在内存的顶部 4Kbyte,我们有一个 NVRAM(非易失性 RAM)。复位向量指向 0xFFF0,因此代码尝试将 cli 指令放置在 0xFFFF0 地址中,而与放置在 init16 标签和 align 16 指令之间的指令数量无关(限于16 字节,因此它可以容纳 1Mbyte)。但是我不明白它是怎么做到的。

我对 align 16times 指令感到特别困扰。因为它们似乎取决于另一个的结果所以我不知道NASM如何解决这个问题。

首先,我们有 times 指令需要 align 16 指令的结果。 times 需要知道 align 16 添加了多少字节才能更改 code_size 标签并用 NOP's.

填充剩余内存

我们还有 align 指令需要知道 times 指令的结果是什么,以便知道 jmp 指令在哪里结束,然后计算如何许多 NOP's 它必须添加才能到达新的 16 位对齐位置。

所以在我看来,这两个指令都取决于另一个指令的结果。

此外,如果在 clijump 之间添加指令,我不明白为什么 cli 指令总是独立地以 0xFFFF0 地址结尾。是objective,但我不知道它是如何工作的。

我认为这两个指令都是一个不确定的系统,所以有很多不同的解决方案。例如,在我认为解决方案可能是之前提供的代码中:

cli指令以0xFFFF1结尾 0xFFFF2 中的 jump 指令 align 16 用 NOP 填充地址 0xFFFF2 到 0xFFFFF 所以现在定义了 code size 标签并且 times 指令用 NOP 的

填充地址 0x0000 到 0xFFFF0

为什么这不是代码的行为?

首先,我觉得看到ORG 0xFF000USE16在一起很奇怪。它认为在实地址模式下,ORG 意味着是 64KB 段中的 16 位偏移量。

这是多通道汇编程序的奇迹

因为在第一次通过时,汇编程序还不知道 endinit_16 标签,它可能只需跳过依赖于它的 times 即可。这会将当前偏移量 ($) 保留在 ORG。然后是编码 cli 和短跳转 jmp init_16 的 3 个字节,然后是 align 16.
产生的 13 个字节 此时,两个标签都是已知的,后续通道可以开始使用这些偏移量。 code_size 计算为 16(两个标签之间的差异),因此 times 填充 4080 nops (4096-16)。
虽然这 2 个标签现在在内存中向上移动了 4080 字节,但它们的差异仍然相同 (16),因此不需要进一步传递。代码已解决

Furthermore, I can't figure why the cli instruction always ends up in the 0xFFFF0 addres independently if add instructions between the cli and jump. It is the objective, but I don't know how it works

在此之后添加一些指令 cli 不会更改概述的过程,只要两个标签之间的差异保持为 16。您可以插入价值 13 个字节的指令。