使用 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 16
和 times
指令感到特别困扰。因为它们似乎取决于另一个的结果所以我不知道NASM如何解决这个问题。
首先,我们有 times
指令需要 align 16
指令的结果。 times
需要知道 align 16
添加了多少字节才能更改 code_size
标签并用 NOP's
.
填充剩余内存
我们还有 align
指令需要知道 times
指令的结果是什么,以便知道 jmp
指令在哪里结束,然后计算如何许多 NOP's
它必须添加才能到达新的 16 位对齐位置。
所以在我看来,这两个指令都取决于另一个指令的结果。
此外,如果在 cli
和 jump
之间添加指令,我不明白为什么 cli
指令总是独立地以 0xFFFF0 地址结尾。是objective,但我不知道它是如何工作的。
我认为这两个指令都是一个不确定的系统,所以有很多不同的解决方案。例如,在我认为解决方案可能是之前提供的代码中:
cli
指令以0xFFFF1结尾
0xFFFF2 中的 jump
指令
align 16
用 NOP 填充地址 0xFFFF2 到 0xFFFFF
所以现在定义了 code size
标签并且 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 个标签现在在内存中向上移动了 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 个字节的指令。
我一直在思考下面的汇编代码(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 16
和 times
指令感到特别困扰。因为它们似乎取决于另一个的结果所以我不知道NASM如何解决这个问题。
首先,我们有 times
指令需要 align 16
指令的结果。 times
需要知道 align 16
添加了多少字节才能更改 code_size
标签并用 NOP's
.
我们还有 align
指令需要知道 times
指令的结果是什么,以便知道 jmp
指令在哪里结束,然后计算如何许多 NOP's
它必须添加才能到达新的 16 位对齐位置。
所以在我看来,这两个指令都取决于另一个指令的结果。
此外,如果在 cli
和 jump
之间添加指令,我不明白为什么 cli
指令总是独立地以 0xFFFF0 地址结尾。是objective,但我不知道它是如何工作的。
我认为这两个指令都是一个不确定的系统,所以有很多不同的解决方案。例如,在我认为解决方案可能是之前提供的代码中:
cli
指令以0xFFFF1结尾
0xFFFF2 中的 jump
指令
align 16
用 NOP 填充地址 0xFFFF2 到 0xFFFFF
所以现在定义了 code size
标签并且 times
指令用 NOP 的
为什么这不是代码的行为?
首先,我觉得看到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 个标签现在在内存中向上移动了 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 个字节的指令。