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