[英]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 处理器。 在 memory 的顶部 4 KB 上,我们有一个 NVRAM(非易失性 RAM)。 重置向量指向 0xFFF0,因此代码尝试将cli
指令放置在 0xFFFF0 地址中,而与放置在init16
label 和align 16
指令之间的指令数量无关(限制为 16 个字节,因此它可以容纳 1Mbyte) . 但我无法理解它是如何做到的。
我对align 16
和times
指令特别困扰。 因为它们似乎依赖于另一个的结果,所以我不知道 NASM 是如何解决这个问题的。
首先,我们有需要align 16
指令结果的times
指令。 times
需要知道align 16
添加了多少字节才能更改code_size
label 并用NOP's
填充 memory 的 rest。
我们还有align
指令,它需要知道times
指令的结果是什么,以便知道jmp
指令在哪里结束,然后计算它必须添加多少NOP's
才能到达新的 16 位对齐 position。
所以在我看来,这两个指令都取决于另一个指令的结果。
此外,如果在cli
和jump
之间添加指令,我无法理解为什么cli
指令总是独立地以 0xFFFF0 地址结束。 这是目标,但我不知道它是如何工作的。
我认为这两个指令都构成了一个未确定的系统,因此有许多不同的解决方案。 例如,在我认为解决方案可能是之前提出的代码中:
cli
指令在 0xFFFF1 结束, jump
指令在 0xFFFF2 和align 16
用 NOP 填充地址 0xFFFF2 到 0xFFFFF 所以现在定义了code size
label 并且times
指令用 NOP 填充地址 0x0000 到 0xFFFF0
为什么这不是代码的行为?
首先,我觉得看到ORG 0xFF000
和USE16
很奇怪。 它认为在实地址模式下, ORG
是 64KB 段中的 16 位偏移量。
因为在第一遍时,汇编器还不知道end和init_16标签,它可以跳过依赖它的times
。 这会将当前偏移量 ($) 保留在ORG
处。 然后是编码cli
和短跳转jmp init_16
的 3 个字节,然后是align 16
产生的 13 个字节。
此时,两个标签都是已知的,并且可以开始使用这些偏移量进行后续传递。 code_size计算为 16(两个标签之间的差异),因此times
填充为 4080 nop
s (4096-16)。
尽管这 2 个标签现在在 memory 中向上移动了 4080 个字节,但它们的差异仍然相同 (16),因此不需要进一步的遍历。 代码已解决。
此外,如果在 cli 和 jump 之间添加指令,我无法理解为什么 cli 指令总是独立地以 0xFFFF0 地址结束。 这是目标,但我不知道它是如何工作的
只要两个标签之间的差异保持 16,在此cli
之后立即添加一些指令不会更改概述的过程。您可以插入价值 13 个字节的指令。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.