JMP直接和JMP与寄存器eax的区别是什么

时间:2017-05-06 02:18:19

标签: assembly x86

我有一个C函数A(),其地址为0x2807fc。我尝试拨打A(),然后按预期跳转到A()

JMP  0x2807fc

但我试试这个,这是错的。为什么?我很困惑。

mov  eax,0x2807fc
JMP  eax

我发现了另一个有趣的问题

002807fc <task_b_main>:
void task_b_main(struct SHEET *sht_back)
{
    2807fc: 55                      push   %ebp
    2807fd: 89 e5                   mov    %esp,%ebp
    2807ff: 83 ec 0c                sub    $0xc,%esp
    struct BOOTINFO *bi = (struct BOOTINFO *)ADR_BOOTINFO;
    ..........
    }

我有一个函数,它的地址是0x2807fc。

然后它是关于JMP的ASM代码和二进制代码(我想跳转到该函数)

appjmp:     
JMP  0x2807fc   ; eip, cs
RET
================
00281310 <appjmp>:
281310: e9 e7 f4 ff ff          jmp    2807fc <task_b_main>
281315: c3 

根据参考资料

Jmp near =>  E9 

E9表示JMP NEAR,为什么地址遵循E9不是fc 07 28 00而是e7 f4 ff ff,我不知道在哪里它来自? (但它确实按预期跳转到了该功能。)

然后我将其修改如下

 appjmp:
 mov  eax,0x2807fc
 JMP  eax  
 ret
 ===================
 00281310 < appjmp >:
 281310:    b8 fc 07 28 00          mov    $0x2807fc,%eax
 281315:    ff e0                   jmp    *%eax
 281317:    c3                      ret  

看起来很正常,但是错了,它无法跳转到该功能。

你能告诉我原因,以及如何改变它以便它可以跳转到这个功能。

#define appjmpTest(addr) \
__asm__ ("ljmp $(3*8), %0" \
        : \
        :"i" (addr))

appjmpTest(&task_b_main-0x280000);

这是我的解决方案。我使用显式segment:offset尝试FAR JMP,然后它可以工作。 (我的C代码位于第三个GDT选择器,因此有$(3 * 8))。

2 个答案:

答案 0 :(得分:1)

  

我尝试调用 A(),并按预期跳转到A()

jmp可以使用ret函数,但如果您没有使用call指令,则无法通过call返回推送堆栈上的返回地址!

  

&#39; E9&#39;表示JMP NEAR,为什么地址遵循&#39; E9&#39;不是fc 07 28 00但是e7 f4 ff ff,我不知道它来自哪里?

那是因为&#39; E9&#39;之后的4个字节。操作码是从此0x002807FC - 0x00281315 ;Destination - NextInstruction 指令末尾到实际目的地的相对位移(在您的情况下为0x002807FC)。
值0xFFFFF4E7的计算公式为:

1. JMP  0x2807fc

2. mov  eax,0x2807fc
   JMP  eax
  

看起来很正常,但是错了,它无法跳转到该功能。

它可能会,但由于该功能无法成功返回,您认为它出错了。

jmp 0x0000:0x2807FC      ;segment,colon,offset  

这两种跳跃方法都是跳到同一位置的接近跳跃。只有第一种方法才能实现跳转,并采用以下形式:

<?php
$color = "black";
if(strlen($row['c_n']) > 11){
    $color = "red";
}
?>
<tr>
    <td style="color:<?php echo $color; ?>>
        <?php echo $row['c_n']; ?>
    </td>
</tr>

当跳跃停留在同一段内时,跳跃被表示为接近 - &gt;英特尔更喜欢称之为段内

当跳跃在片段之间时,跳跃被表示为 - &GT;英特尔更喜欢称之为段落

附近这些概念与距离无关!

答案 1 :(得分:0)

JMP  0x2807fc

和这个

mov  eax,0x2807fc
JMP  eax

不等同。

最佳来源是英特尔manuals - 在本案例中为第2A卷,第3-488节

首先属于这一类:

  

JMP rel32

     

跳近,相对,RIP = RIP + 32位位移符号扩展到   64位

第二个:

  

JMP r / m32

     

跳转,绝对间接,r / m32中给出的地址。不支持   64位模式。

相对vs绝对 - &gt;如果EIP!= 0,则首先赢得与第二个地址相同的地址。

如果你在代码中使用绝对地址(真的??)或标签并让汇编程序进行翻译,这是不明显的。