在学校,我们一直使用引导程序来运行没有操作系统的独立程序.我一直在研究这个程序,当启用保护模式时,通过直接将操作码和操作数组合为程序中的数据来执行远程跳转.这是为GNU汇编程序:
/* this code immediately follows the setting of the PE flag in CR0 */.byte 0x66, 0xEA .long TARGET_ADDRESS .word 0x0010 /* descriptor #2, GDT, RPL=0 */首先,为什么要这样做(而不是指令助记符)?
我一直在看英特尔的手册,但我仍然对代码感到困惑.特别是在第2A卷第3-549页,有一个操作码表.相关条目:
EA *cp* JMP ptr16:32 Inv. Valid Jump far, absolute, address given in operand实际的操作码是显而易见的,但是第一个字节0x66让我感到困惑.参考英特尔手册中的表格,cp显然意味着将遵循一个6字节的操作数.显然,在接下来的两行中会有6个字节.0x66编码'操作数大小覆盖前缀'.这与表中的cp有什么关系?我原以为cp会有一些十六进制值,而是有这个覆盖前缀.有人可以帮我清楚一下吗?
这是od的转储:
c022 **ea66 0000 0001 0010** ba52 03f2 c030TARGET_ADDRESS定义为0x00010000.
我也对最后两个字节的重要性感到困惑.然而,这似乎是另一个问题.现在已经很晚了,我一直盯着代码和英特尔手册几个小时,所以我希望我明白我的观点.
谢谢你的期待!
1> Diego Sevill..:0x66表示JMP(0xEA)指的是六个字节.默认值是在实模式下指向64K(16位)或在保护模式下指向32位(如果我记得很清楚).增加它后,它还包括段描述符,GDT或LDT中段的索引,这意味着,此代码正在进行传统上称为"长跳转"的跳转:跳过超出段的段x86架构.在这种情况下,该段指向GDT上的第二个条目.如果您在该程序中查看之前,您可能会看到GDT是如何根据段起始地址和长度定义的(请参阅英特尔手册以研究GDT和LDT表,32位条目描述每个段).