2013-12-22 39 views

回答

6

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

要跳转到下一条指令(实际上不跳了跳),你做

jmp $+2 

因此,跳过N字节过去JMP指令,你会做什么:

jmp $+2+N 

在你的榜样,4 NOP的

jmp $+6 

汇编应该检测,这是一个跳转到近地址并将其组装为短暂的跳跃。如果想确定,使用

jmp short $+6 
+0

这就是我正在寻找的! :)还有一件事:我可以使用带偏移量的条件跳转指令集吗?例如'''je $ + N;'''? – alexandernst

+0

我不明白你为什么做不到。条件短分支使用两个字节,所以过程与无条件短跳转相同。 –

+0

谢谢,先生!你对我最后几个问题的回答是完美的。格拉西亚斯 – alexandernst

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); 
    } 
    } 
} 

我更喜欢使用内联填充断点说明,我不打算执行, 的理由是,如果它得到执行,该处理器将陷阱我会发现它的。你可以在“默认”情况下看到。

+0

实际上4个字节的NOP只是一个例子。我想要做的是“跳过”N个字节的指令。 – alexandernst

+0

我不明白当你说rel跳转只有2或5个字节时你的意思是什么。不能跳过“跳过”我想要的任何字节数量,从-127到+127?另外,我可以使用带偏移的条件跳转指令吗?例如'''je $ + N;'''? – alexandernst

+0

@alexandernst:这个函数告诉你为了跳过N个字节而发出的代码。通常应该优先考虑nop;处理器非常快地执行它们,并且jmp应该保留在nop不起作用的地方。相对的jmps是* size *中的2或5个字节,所以不能使用5字节的jmp填充4字节的空洞,或者使用2字节的jmp填充1字节的hold。是的,你可以使用相对jmp填充大约+120个奇数字节;正如我所说的,检查默认开关盒来查看它产生的内容。 –