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

5

我已经思考了一段时间以下的汇编代码(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处理器,内存顶部的4K字节上有一块NVRAM(非易失性RAM)。复位向量指向0xFFF0,因此代码尝试将cli指令放置在0xFFFF0地址,无论在init16标签和align 16指令之间放置了多少指令(限制为16字节以适应1MB内存)。但我不明白它是如何做到这一点的。
我特别困扰于align 16times指令。因为它们似乎取决于彼此的结果,所以我不知道NASM是如何解决这个问题的。
首先,我们有times指令需要align 16指令的结果。times需要知道align 16添加了多少字节,以更改code_size标签并用NOP填充剩余的内存空间。
我们还有一个align指令需要知道times指令的结果,以确定jmp指令结束的位置,然后计算要添加多少NOP以达到新的16位对齐位置。
因此,对我来说,这两个指令都取决于对方的结果。
此外,我不明白为什么cli指令总是最终独立在0xFFFF0地址上,即使在clijump之间添加了指令。这是目标,但我不知道它是如何工作的。
我认为这两个指令会产生不确定的系统,因此有许多不同的解决方案。例如,在我之前提出的代码中,我认为一种解决方案可能是: cli指令最终在0xFFFF1处。 jump指令在0xFFFF2处。 align 16使用NOP填充地址0xFFFF2到0xFFFFF。 因此,code size标签现在已被定义,times指令用NOP填充地址0x0000到0xFFFF0。
为什么这不是代码的行为?
1个回答

5
首先,我认为在实模式下,“ORG”应该是一个64KB段中的16位偏移量,因此与“USE16”一起使用时,看到“ORG 0xFF000”有些奇怪。

这是多通道汇编器的奇妙之处

因为在第一通道中,汇编器尚不知道“end”和“init_16”标签,因此可以跳过依赖于它们的“times”。这将使当前偏移量($)留在“ORG”处。然后是由“cli”编码产生的3个字节和短跳转“jmp init_16”的2个字节,接着是由“align 16”生成的13个字节。
此时,两个标签都已知,下一通道可以开始使用这些偏移量。计算“code_size”为16(两个标签之间的差异),因此“times”用4080个“nop”填充(4096-16)。
虽然现在这2个标签向上移动了4080字节,但它们之间的差异仍然相同(16),因此无需进行进一步的处理。代码已经解决。

此外,我无法想象为什么“cli”指令始终以独立于“如果在cli和jump之间添加指令”而言的0xFFFF0地址结尾。这是目标,但我不知道它是如何工作的

在这个“cli”后面添加几条指令并不会改变已概述的过程,只要两个标签之间的差异保持为16。您可以插入价值13字节的指令。

非常感谢!现在我明白了! - Gaston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接