assembly - 有人可以解释一下这个直接组装的 x86 JMP 操作码吗?

标签 assembly x86 gnu opcode protected-mode

在学校,我们一直使用 Bootstrap 来运行没有操作系统的独立程序。我一直在研究这个程序,当启用保护模式时,通过直接将操作码和操作数组装为程序中的数据来执行远跳转。这是针对 GNU 汇编器的:


         /* this code immediately follows the setting of the PE flag in CR0 */<p></p>

<pre><code>.byte   0x66, 0xEA
.long   TARGET_ADDRESS
.word   0x0010          /* descriptor #2, GDT, RPL=0 */
</code></pre>

<p></p>

首先,为什么要这样做(而不是指令助记符)?

我一直在查看英特尔手册,但对代码仍然有点困惑。具体来说,在第 2A 卷第 3-549 页中,有一个操作码表。相关条目:

EA *cp* JMP ptr16:32  Inv.  Valid  Jump far, absolute, address given in
operand

实际的操作码很明显,但第一个字节 0x66 让我感到困惑。引用Intel手册中的表格,cp显然意味着后面将有一个6字节的操作数。显然接下来的两行是 6 个字节。 0x66 编码“操作数大小覆盖前缀”。这和表中的cp有什么关系呢?我原以为 cp 有一些十六进制值,但有这个覆盖前缀。有人可以帮我解决这个问题吗?

这是来自 od 的转储:

c022    **ea66    0000    0001    0010**    ba52    03f2    c030

TARGET_ADDRESS 被定义为 0x00010000。

我也对最后两个字节的重要性感到有点困惑。然而,这似乎完全是另一个问题。现在已经很晚了,我已经盯着代码和英特尔手册几个小时了,所以我希望我能明白我的观点。

感谢您的浏览!

最佳答案

0x66 表示 JMP (0xEA) 指的是 6 个字节。默认值是指实模式下的 64K(16 位)或保护模式下的 32 位(如果我没记错的话)。增加它后,它还包括段描述符,即 GDT 或 LDT 中段的索引,这意味着该代码正在执行传统上称为“长跳转”的操作:跨越 GDT 中的段的跳转。 x86架构。在本例中,该段指向 GDT 上的第二个条目。如果您之前查看过该程序,您可能会看到 GDT 是如何根据段起始地址和长度定义的(查看 Intel 手册以研究 GDT 和 LDT 表,描述每个段的 32 位条目)。

关于assembly - 有人可以解释一下这个直接组装的 x86 JMP 操作码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/545093/

相关文章:

linux - 表中元素的总和与汇编

function - Delphi - 编写带有函数的 .pas 库

operating-system - 推荐一个简单的 x86 模拟器和操作系统

c - 段错误 - GNU C

c++ - 使用 cmake 设置 gsl 时出现问题

makefile - 为什么 .SECONDARY 不适用于模式 (%) 而 .PRECIOUS 可以?

assembly - 如何在气体汇编代码中导出类型为 "FUNC"和 "GLOBAL"的符号?

c - 在 Assembly x86 中获取三个数字的最大值时出现段错误

linux - __libc_start_main@plt 是如何工作的?

在 C 中调用函数