短jmp指令的语法

时间:2013-12-22 15:03:52

标签: assembly

我正在阅读http://thestarman.pcministry.com/asm/2bytejumps.htm,但文字不清楚如何对偏移量进行JMP(不使用标签而跳转到相对地址)。

假设我有

NOP
NOP
NOP
NOP

(这是4个字节的指令),我想跳过它们(跳过4个字节)。我会写什么?

jmp $+4;

jmp $+2+4;

2 个答案:

答案 0 :(得分:7)

一个简短的jmp操作码使用两个字节。汇编时,当前位置($)指向JMP指令的开头,而不是指向下一条指令的开头。

要跳转到下一条指令(实际上没有跳转的跳转),你可以

jmp $+2

因此,要跳过JMP指令的N个字节,您将执行:

jmp $+2+N

在你的例子中,4 NOP的

jmp $+6

汇编程序应检测到这是跳转到近地址并将其组合为短跳转。如果想确定,请使用

jmp short $+6

答案 1 :(得分:1)

使用单个jmp“跳过”4个字节是不方便的,因为相对的jmps占用2或5个字节。

要跳过(总共)4个字节,您可以这样做:

  jmp   short $+4   ; the "short" forces a 2 byte relative branch
  nop
  nop

如果你的问题是要填写适当数量的N个字节,你应该发出一个适当大小的nop。 这是我在编写的编译器中使用的内容:

void ObjectCodeEmitNByteNop(natural n)
{ // See http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2010-September/003881.html GOOD INFO
  /* The Intel Architecture Software developer's guide, volume 2B (instructions N-Z) contains the following table (pg 4-12) about NOP:

Table 4-9. Recommended Multi-Byte Sequence of NOP Instruction

Length    Assembly                                   Byte Sequence
=================================================================================
2 bytes   66 NOP                                     66 90H
3 bytes   NOP DWORD ptr [EAX]                        0F 1F 00H
4 bytes   NOP DWORD ptr [EAX + 00H]                  0F 1F 40 00H
5 bytes   NOP DWORD ptr [EAX + EAX*1 + 00H]          0F 1F 44 00 00H
6 bytes   66 NOP DWORD ptr [EAX + EAX*1 + 00H]       66 0F 1F 44 00 00H
7 bytes   NOP DWORD ptr [EAX + 00000000H]            0F 1F 80 00 00 00 00H
8 bytes   NOP DWORD ptr [EAX + EAX*1 + 00000000H]    0F 1F 84 00 00 00 00 00H
9 bytes   66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00 00H
  */
  switch(n)
  { 
case 0:
  break;  // accidentally aligned
case 1:
  ObjectCodeEmitByte(0x90); // sequence recommended by AMD optimization manual
  break;
case 2:
  ObjectCodeEmitWord(0x9066); // sequence recommended by AMD and Intel optimization manual
      // MS assembler suggests:  ObjectCodeEmitWord(0xFF8B); "MOV EDI,EDI"
  break;
case 3: 
      ObjectCodeEmitThreeByteNOP();
      break;
case 4:        
  ObjectCodeEmitFourByteNOP();
      // ObjectCodeEmitDword(0x90666666); // sequence recommended by AMD optimization manual
      // MS assembler suggests: ObjectCodeEmitDword(0x0024648D); // LEA ESP,0[ESP]
  break;
    case 5:
#if 0
  ObjectCodeEmitByte(0x05); // ADD EAX, imm32
  ObjectCodeEmitDword(0);
#else
  ObjectCodeEmitByte(0x0F); // NOP ...
      ObjectCodeEmitDword(0x0000441F); // ... DWORD ptr [EAX + EAX*1 + 00H]
#endif
      break;
   case 6:
  ObjectCodeEmitWord(0x9B8D); // LEA EBX,disp32[EBX]  (Microsoft assembler emits this)
  ObjectCodeEmitDword(0x00000000); // offset = 0 --> don't change EBX
      break;
case 7:
  ObjectCodeEmitByte(0x8D); // LEA opcode byte
  ObjectCodeEmitWord(0x24A4); // ESP,disp32[ESP]
  ObjectCodeEmitDword(0x00000000); // offset = 0 --> don't change ESP
      break;
case 8:
  ObjectCodeEmitDword(0x00841F0F); // NOP DWORD ptr [EAX + EAX*1 + ...
      ObjectCodeEmitDword(0x00000000); // ...00000000H]
      break;
    case 9:
      ObjectCodeEmitByte(0x66); // 66 0F 1F 84 00 00 00 00 00H
      ObjectCodeEmitDword(0x00841F0F); // NOP DWORD ptr [EAX + EAX*1 + ...
      ObjectCodeEmitDword(0x00000000); // ...00000000H]
      break;
default:
      { ObjectCodeEmitJmpRelativeShort(ObjectCodeSize+n);
        // ObjectCodeEmitJmpRelativeLong(DesiredObjectLocation); // 5 bytes is safe; 1-4 bytes handled above
        ObjectCodeEmitNBreakpoints(n-2);
  }
  }
}

我更喜欢使用断点指令进行内联填充,我不打算执行, 因为如果它被执行,处理器将陷阱,我会发现它。您可以在“默认”情况下看到它。