明白なことは、関心のあるマシン命令の要素の生成を表す抽象化のセットを構築し、次に必要な命令/アドレッシングモードを得るための呼び出しを作成することです。幅広い種類のコードを生成すると、このようにして命令セット全体をエンコードすることができます。
ObjectCodeEmitMovRegister32ScaledRegister32OffsetRegister32(EAX,EDX,4,-LowerBound*4,ESP);
あなたは、私が長い名前が好きで伝えることができます:
そして、MOV命令を生成するために、あなたは次のようなコードを書くことができます。 (少なくとも彼らが何をしているか決して忘れることはありません)
私はC言語で実装されたこれをサポートしているコードジェネレータの一部です。これは、MODとSIBバイトの生成という最も難しい部分の種類を網羅しています。このスタイルに従って、好きなように多くの命令セットを実装できます。この例はx32のみに適用されるため、OPはそれに応じて拡張および変更する必要があります。 MOV命令ジェネレータの定義は最後に終了しています。
#define Register32T enum Register32Type
enum Register32Type {EAX=0,ECX=1,EDX=2,EBX=3,ESP=4,EBP=5,ESI=6,EDI=7};
inline
byte ObjectCodeEmitModRM32Register32(Register32T Register32,Register32T BaseRegister32)
// Send ModRM32Bytes for register-register mode to object file
{ byte ModRM32Byte=0xC0+Register32*0x8+BaseRegister32;
ObjectCodeEmitByte(ModRM32Byte);
return ModRM32Byte;
}
inline
byte ObjectCodeEmitModRM32Direct(Register32T Register32)
// Send ModRM32Bytes for direct address mode to object file
{ byte ModRM32Byte=Register32*0x8+0x05;
ObjectCodeEmitByte(ModRM32Byte);
return ModRM32Byte;
}
inline
void ObjectCodeEmitSIB(Register32T ScaledRegister32,
natural Scale,
Register32T BaseRegister32)
// send SIB byte to object file
// Note: Use ESP for ScaledRegister32 to disable scaling; only useful when using ESP for BASE.
{ if (ScaledRegister32==ESP && BaseRegister32!=ESP) CompilerFault(31);
if (Scale==1) ObjectCodeEmitByte((byte)(0x00+ScaledRegister32*0x8+BaseRegister32));
else if (Scale==2) ObjectCodeEmitByte((byte)(0x40+ScaledRegister32*0x8+BaseRegister32));
else if (Scale==4) ObjectCodeEmitByte((byte)(0x80+ScaledRegister32*0x8+BaseRegister32));
else if (Scale==8) ObjectCodeEmitByte((byte)(0xC0+ScaledRegister32*0x8+BaseRegister32));
else CompilerFault(32);
}
inline
byte ObjectCodeEmitModRM32OffsetRegister32(Register32T Register32,
integer Offset,
Register32T BaseRegister32)
// Send ModRM32Bytes for indexed address mode to object file
// Returns 1st byte of ModRM32 for possible use in EmittedPushRM32 peephole optimization
{ byte ModRM32Byte;
if (Offset==0 && BaseRegister32!=EBP)
{ ModRM32Byte=0x00+Register32*0x8+BaseRegister32;
ObjectCodeEmitByte(ModRM32Byte);
if (BaseRegister32==ESP) ObjectCodeEmitSIB(ESP,1,ESP);
}
else if (Offset>=-128 && Offset<=127)
{ ModRM32Byte=0x40+Register32*0x8+BaseRegister32;
ObjectCodeEmitByte(ModRM32Byte);
if (BaseRegister32==ESP) ObjectCodeEmitSIB(ESP,1,ESP);
ObjectCodeEmitByte((byte)Offset);
}
else { // large offset
ModRM32Byte=0x80+Register32*0x8+BaseRegister32;
ObjectCodeEmitByte(ModRM32Byte);
if (BaseRegister32==ESP) ObjectCodeEmitSIB(ESP,1,ESP);
ObjectCodeEmitDword(Offset);
}
return ModRM32Byte;
}
inline
byte ObjectCodeEmitModRM32OffsetScaledRegister32(Register32T Register32,
integer Offset,
Register32T ScaledRegister32,
natural Scale)
// Send ModRM32Bytes for indexing by a scaled register with no base register to object file
// Returns 1st byte of ModRM32 for possible use in EmittedPushRM32 peephole optimization
{ byte ModRM32Byte=0x00+Register32*0x8+ESP;
ObjectCodeEmitByte(ModRM32Byte); // MOD=00 --> SIB does disp32[index]
ObjectCodeEmitSIB(ScaledRegister32,Scale,EBP);
ObjectCodeEmitDword(Offset);
return ModRM32Byte;
}
inline
byte ObjectCodeEmitModRM32ScaledRegister32OffsetRegister32(Register32T Register32,
Register32T ScaledRegister32,
natural Scale,
integer Offset,
Register32T BaseRegister32)
// Send ModRM32Bytes for indexed address mode to object file
// Returns 1st byte of ModRM32 for possible use in EmittedPushRM32 peephole optimization
// If Scale==0, leave scale and scaled register out of the computation
{ byte ModRM32Byte;
if (Scale==0) ObjectCodeEmitModRM32OffsetRegister32(Register32,Offset,BaseRegister32);
else if (Offset==0 && BaseRegister32!=EBP)
{ ModRM32Byte=0x00+Register32*0x8+ESP;
ObjectCodeEmitByte(ModRM32Byte);
ObjectCodeEmitSIB(ScaledRegister32,Scale,BaseRegister32);
}
else if (Offset>=-128 && Offset<=127)
{ ModRM32Byte=0x40+Register32*0x8+ESP;
ObjectCodeEmitByte(ModRM32Byte);
ObjectCodeEmitSIB(ScaledRegister32,Scale,BaseRegister32);
ObjectCodeEmitByte((byte)Offset);
}
else { // large offset
ModRM32Byte=0x80+Register32*0x8+ESP;
ObjectCodeEmitByte(ModRM32Byte);
ObjectCodeEmitSIB(ScaledRegister32,Scale,BaseRegister32);
ObjectCodeEmitDword(Offset);
}
return ModRM32Byte;
}
inline
void ObjectCodeEmitLeaRegister32OffsetRegister32ScaledPlusBase32(
Register32T Register32Destination,
integer Offset,
Register32T Register32Source,
natural Scale, // 1,2,4 or 8
Register32T Base)
// send "LEA Register32,offset[Register32*Scale+Base]" to object file
{ ObjectCodeEmitLeaOpcode();
ObjectCodeEmitModRM32ScaledRegister32OffsetRegister32(
Register32Destination,Register32Source,Scale,Offset,Base);
}
inline
void ObjectCodeEmitMovRegister32ScaledRegister32OffsetRegister32(Register32T DestinationRegister32,
Register32T ScaledRegister32,
natural Scale,
integer Offset,
Register32T BaseRegister32)
// Emit Mov R32 using scaled index addressing
{ ObjectCodeEmitMovRegister32Opcode();
ObjectCodeEmitModRM32ScaledRegister32OffsetRegister32(DestinationRegister32,
ScaledRegister32,
Scale,
Offset,
BaseRegister32);
}
これはインラインアセンブリではないため、インラインマシンコードです! –
なぜこれを行う必要がありますか? GetCurrentProcess()をCコードから直接呼び出さないのはなぜですか? – user9876
@ user9876:リモート(中断)プロセスでコードを修正しています。このプログラムは、Unixシステム上で 'LD_PRELOAD'と同様の影響を与えます。 –