我在阅读http://thestarman.pcministry.com/asm/2bytejumps.htm,但文本不太清楚如何对偏移量(不使用标签的短跳转到相对地址)执行JMP
。短jmp指令的语法
比方说,我有
NOP
NOP
NOP
NOP
(也就是4个字节的指令),我想跳过它们(跳过4个字节)。我会写什么?
jmp $+4;
?
jmp $+2+4;
?
我在阅读http://thestarman.pcministry.com/asm/2bytejumps.htm,但文本不太清楚如何对偏移量(不使用标签的短跳转到相对地址)执行JMP
。短jmp指令的语法
比方说,我有
NOP
NOP
NOP
NOP
(也就是4个字节的指令),我想跳过它们(跳过4个字节)。我会写什么?
jmp $+4;
?
jmp $+2+4;
?
简短的jmp操作码使用两个字节。汇编时,当前位置($
)指向JMP指令的开始位置,而不是指向下一条指令的开始位置。
要跳转到下一条指令(实际上不跳了跳),你做
jmp $+2
因此,跳过N字节过去JMP指令,你会做什么:
jmp $+2+N
在你的榜样,4 NOP的
jmp $+6
汇编应该检测,这是一个跳转到近地址并将其组装为短暂的跳跃。如果想确定,使用
jmp short $+6
使用单个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);
}
}
}
我更喜欢使用内联填充断点说明,我不打算执行, 的理由是,如果它得到执行,该处理器将陷阱我会发现它的。你可以在“默认”情况下看到。
实际上4个字节的NOP只是一个例子。我想要做的是“跳过”N个字节的指令。 – alexandernst
我不明白当你说rel跳转只有2或5个字节时你的意思是什么。不能跳过“跳过”我想要的任何字节数量,从-127到+127?另外,我可以使用带偏移的条件跳转指令吗?例如'''je $ + N;'''? – alexandernst
@alexandernst:这个函数告诉你为了跳过N个字节而发出的代码。通常应该优先考虑nop;处理器非常快地执行它们,并且jmp应该保留在nop不起作用的地方。相对的jmps是* size *中的2或5个字节,所以不能使用5字节的jmp填充4字节的空洞,或者使用2字节的jmp填充1字节的hold。是的,你可以使用相对jmp填充大约+120个奇数字节;正如我所说的,检查默认开关盒来查看它产生的内容。 –
这就是我正在寻找的! :)还有一件事:我可以使用带偏移量的条件跳转指令集吗?例如'''je $ + N;'''? – alexandernst
我不明白你为什么做不到。条件短分支使用两个字节,所以过程与无条件短跳转相同。 –
谢谢,先生!你对我最后几个问题的回答是完美的。格拉西亚斯 – alexandernst