Gas*_*ton 5 x86 assembly nasm osdev
我一直在考虑以下汇编代码(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 :
Run Code Online (Sandbox Code Playgroud)
这只是一个例子。这个想法是我们在实模式下有一个 IA-32 处理器。在内存的顶部 4 KB 上,我们有一个 NVRAM(非易失性 RAM)。复位向量指向 0xFFF0,因此代码尝试将cli指令放置在 0xFFFF0 地址中,而与放置在init16标签和align 16指令之间的指令数量无关(限制为 16 字节,因此可以适应 1M 字节)。但我无法理解它是如何做到的。
我对align 16和times指令特别困扰。因为它们似乎取决于另一个的结果,所以我不知道 NASM 是如何解决这个问题的。
首先,我们有times需要指令结果的align 16指令。times需要知道align 16添加了多少字节才能更改code_size标签并用NOP's.
我们还有一个align指令,它需要知道指令的结果是什么times,以便知道指令在哪里jmp结束,然后计算NOP's它必须添加多少才能到达新的 16 位对齐位置。
所以在我看来,这两个指令都取决于另一个指令的结果。
此外,cli如果在cli和之间添加指令,我无法弄清楚为什么指令总是独立地以 0xFFFF0 地址结束jump。这是目标,但我不知道它是如何工作的。
我认为这两个指令都构成了一个未确定的系统,因此有许多不同的解决方案。例如,在我之前提出的代码中,我认为解决方案可能是:
该cli指令0xFFFF1结束了jump在0xFFFF2指令和align 16与NOP的填充地址0xFFFF2到0xFFFFF所以code size标签现在定义和times指令填充地址0x0000〜0xFFFF0与NOP的
为什么这不是代码的行为?
首先,我觉得ORG 0xFF000和USE16. 它认为在实地址模式下,ORG意味着在 64KB 段中是 16 位偏移量。
因为在第一遍时,汇编器还不知道end和init_16标签,它可以跳过times依赖于它的标签。这会将当前偏移量 ($) 保留在ORG. 然后是编码cli和短跳转的 3 个字节jmp init_16,然后是align 16.
此时,两个标签都是已知的,接下来的传递可以开始使用这些偏移量。code_size计算为 16(两个标签之间的差异),因此times填充 4080nop秒(4096-16)。
尽管这 2 个标签现在在内存中向上移动了 4080 字节,但它们的差异仍然相同 (16),因此不需要进一步传递。代码已解决。
此外,如果在 cli 和 jump 之间添加指令,我无法弄清楚为什么 cli 指令总是独立地以 0xFFFF0 地址结束。这是目标,但我不知道它是如何工作的
cli只要两个标签之间的差值保持为 16,在此之后立即添加一些指令不会改变概述的过程。您可以插入价值 13 字节的指令。