#include "../BasicCompiler_Common/common.h" #include "Opcode.h" BOOL IsSafeReg(int reg){ if(reg==REG_EBX||reg==REG_ESI||reg==REG_EDI) return 1; return 0; } ///////////////////////////////////////////////// // ModR/Mバイト、SIBバイト、ディスプレースメント ///////////////////////////////////////////////// //スケール #define SCALE_NON (char)0x00 #define SCALE_2 (char)0x40 #define SCALE_4 (char)0x80 #define SCALE_8 (char)0xC0 //インデックスなし #define INDEX_NON 0x04 void set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,int disp){ if(mod==MOD_DISP32){ //ModR/Mバイト OpBuffer[obp++]=(char)( REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(0x04)); base_reg=0x05; index_reg=INDEX_NON; } else{ //ModR/Mバイト OpBuffer[obp++]=(char)(mod | REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(base_reg)); } //レジスタモードの場合は、ここで終了 if(mod==MOD_REG) return; if(REGISTER_OPERAND(base_reg)==0x04||mod==MOD_DISP32){ ////////////////////// // SIBバイトを使う ////////////////////// OpBuffer[obp++]=(char)(scale| REGISTER_OPERAND(index_reg)<<3 | REGISTER_OPERAND(base_reg)); } //ディスプレースメントを必要としない場合は、ここで終了 if(mod==MOD_BASE) return; ////////////////////////// // ディスプレースメント ////////////////////////// if(mod==MOD_BASE_DISP8) OpBuffer[obp++]=(char)disp; else{ *((long *)(OpBuffer+obp))=disp; obp+=sizeof(long); } } void __op_format(char op_prefix,char opcode,int reg){ //命令プリフィックス if(op_prefix) OpBuffer[obp++]=op_prefix; //オペコード、レジスタ OpBuffer[obp++]=(char)(opcode|REGISTER_OPERAND(reg)); } void __op_format(char op_prefix,char opcode1,char opcode2,int reg,int base_reg,int offset,char mod){ //命令プリフィックス if(op_prefix) OpBuffer[obp++]=op_prefix; //オペコード OpBuffer[obp++]=opcode1; if(opcode2) OpBuffer[obp++]=opcode2; //ModR/M, SIB, disp set_mod_rm_sib_disp(mod,reg,SCALE_NON,INDEX_NON,base_reg,offset); } /////////////////// // mov関連 /////////////////// void op_mov_RV(int reg,int offset){ //mov reg,value //オペコード、レジスタ OpBuffer[obp++]=(char)(0xB8|REGISTER_OPERAND(reg)); //DISP32 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } void op_mov_RV(int op_size,int reg,int offset){ if(op_size==PTR_SIZE) op_mov_RV(reg,offset); else SetError(300,NULL,cp); } void op_mov_RR(int reg1,int reg2){ //mov reg1,reg2 if(reg1==reg2) return; //1000 1011 11xx xbbb OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)); } void op_mov_RM(int op_size,int reg,int base_reg,int offset,char mod){ //mov reg32,dword ptr[base_reg+offset] //mov reg16,word ptr[base_reg+offset] //mov reg8,byte ptr[base_reg+offset] //16ビット演算の命令プリフィックス char op_prefix=0; if(op_size==sizeof(short)) op_prefix=(char)0x66; //オペコード char opcode; if(op_size==sizeof(char)) opcode=(char)0x8A; else opcode=(char)0x8B; __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod); } void op_mov_RM_ex(int op_size,int reg,int base_reg1,int base_reg2,int offset,BOOL bUseOffset){ //mov reg32,dword ptr[base_reg1+base_reg2+offset] //mov reg16,word ptr[base_reg1+base_reg2+offset] //mov reg8,byte ptr[base_reg1+base_reg2+offset] if(base_reg1==REG_ESP){ //SIBバイトのindex部にespは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //16ビット演算のプリフィックス if(op_size==sizeof(short)) OpBuffer[obp++]=(char)0x66; //オペコード if(op_size==sizeof(char)) OpBuffer[obp++]=(char)0x8A; else OpBuffer[obp++]=(char)0x8B; if(bUseOffset){ /////////////////////////// // オフセット値を使う /////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x84| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); //オフセット値 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } else{ /////////////////////////// // オフセット値を使わない /////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x04| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); } } void op_mov_MR(int op_size,int reg,int base_reg,int offset,char mod){ //mov dword ptr[base_reg+offset],reg32 //mov word ptr[base_reg+offset],reg16 //mov byte ptr[base_reg+offset],reg8 //16ビット演算の命令プリフィックス char op_prefix=0; if(op_size==sizeof(short)) op_prefix=(char)0x66; //オペコード char opcode; if(op_size==sizeof(char)) opcode=(char)0x88; else opcode=(char)0x89; __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod); } void op_mov_MR_ex(int op_size,int reg,int base_reg1,int base_reg2,int offset,BOOL bUseOffset){ //mov dword ptr[base_reg1+base_reg2+offset],reg32 //mov word ptr[base_reg1+base_reg2+offset],reg16 //mov byte ptr[base_reg1+base_reg2+offset],reg8 if(base_reg1==REG_ESP){ //SIBバイトのindex部にrspは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //16ビット演算のプリフィックス if(op_size==sizeof(short)) OpBuffer[obp++]=(char)0x66; //オペコード if(op_size==sizeof(char)) OpBuffer[obp++]=(char)0x88; else OpBuffer[obp++]=(char)0x89; if(bUseOffset==USE_OFFSET){ ////////////////////////// //オフセット値を使う ////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x84| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); //オフセット値 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } else{ ////////////////////////// //オフセット値を使わない ////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x04| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); } } //////////////////////////////// // movsx関連 //////////////////////////////// void op_movsx_R32R16(int reg32,int reg16){ //movsx reg32,reg16 //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x0F; char opcode2=(char)0xBF; __op_format(op_prefix,opcode,opcode2,reg32,reg16,0,MOD_REG); } void op_movsx_R32R8(int reg32,int reg8){ //movsx reg32,reg8 //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x0F; char opcode2=(char)0xBE; __op_format(op_prefix,opcode,opcode2,reg32,reg8,0,MOD_REG); } void op_movsx_R16R8(int reg16,int reg8){ //movsx reg16,reg8 //16ビット演算の命令プリフィックス char op_prefix=(char)0x66; //オペコード char opcode=(char)0x0F; char opcode2=(char)0xBE; __op_format(op_prefix,opcode,opcode2,reg16,reg8,0,MOD_REG); } ////////////////////////////////// // インクリメント・デクリメント ////////////////////////////////// void op_inc(int reg){ //inc reg //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0xFF; __op_format(op_prefix,opcode,0,0,reg,0,MOD_REG); } void op_dec(int reg){ op_inc(reg); OpBuffer[obp-1]=OpBuffer[obp-1]|0x08; } ///////////////////// // add関連 ///////////////////// void op_add_RV8(int reg,char cValue){ //add reg,value8 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)(0xC0|REGISTER_OPERAND(reg)); OpBuffer[obp++]=cValue; } void op_add_RM(int op_size,int reg,int base_reg,int offset,char mod){ //add reg32,dword ptr[base_reg+offset] //add reg16,word ptr[base_reg+offset] //add reg8,byte ptr[base_reg+offset] //16ビット演算の命令プリフィックス char op_prefix=0; if(op_size==sizeof(short)) op_prefix=(char)0x66; //オペコード char opcode; if(op_size==sizeof(char)) opcode=(char)0x02; else opcode=(char)0x03; __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod); } void op_adc_RV8(int reg,char cValue){ //adc reg,value8 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)(0xD0|REGISTER_OPERAND(reg)); OpBuffer[obp++]=cValue; } ///////////////////// // sub関連 ///////////////////// void op_sub_RV8(int reg,char cValue){ //sub reg,value8 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)(0xE8|REGISTER_OPERAND(reg)); OpBuffer[obp++]=cValue; } void op_sbb_RV8(int reg,char cValue){ //sbb reg,value8 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)(0xD8|REGISTER_OPERAND(reg)); OpBuffer[obp++]=cValue; } void op_sbb_RR( int reg1, int reg2 ){ //sbb reg1,reg2 //オペコード OpBuffer[obp++]=(char)0x1B; //レジスタ OpBuffer[obp++]=(char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)); } ////////////////////// // and関連 ////////////////////// void op_and_RV(int reg,int value){ //and reg,value if(reg==REG_RAX){ //eaxのみ特殊 // [8bit rex] 0010 0101 [32bit offset] OpBuffer[obp++]=(char)0x25; *((long *)(OpBuffer+obp))=value; obp+=sizeof(long); } else{ //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x81; __op_format(op_prefix,opcode,0,0,reg,value,MOD_REG); } } void op_or_RR( int op_size, int reg1, int reg2 ){ //16ビット演算のプリフィックス if(op_size==sizeof(short)) OpBuffer[obp++]=(char)0x66; //オペコード if(op_size==sizeof(char)) OpBuffer[obp++]=(char)0x0A; else OpBuffer[obp++]=(char)0x0B; //レジスタ OpBuffer[obp++]=(char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)); } void op_neg( int reg ){ //neg reg //オペコード OpBuffer[obp++]=(char)0xF7; //レジスタ OpBuffer[obp++]=(char)(0xD8| REGISTER_OPERAND(reg)); } /////////////////////// // 64ビット関連 /////////////////////// void op_cdq(){ //cdq OpBuffer[obp++]=(char)0x99; } ///////////////////// // ストリング関係 ///////////////////// void op_rep_movs(int op_size){ if(op_size==sizeof(BYTE)){ //rep movs byte ptr[edi],byte ptr[esi] OpBuffer[obp++]=(char)0xF3; OpBuffer[obp++]=(char)0xA4; } else if(op_size==sizeof(short)){ //rep movs word ptr[edi],word ptr[esi] OpBuffer[obp++]=(char)0xF3; OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0xA5; } else if(op_size==sizeof(long)){ //rep movs dword ptr[edi],dword ptr[esi] OpBuffer[obp++]=(char)0xF3; OpBuffer[obp++]=(char)0xA5; } } ////////////////////////// // スタック関連 ////////////////////////// void op_push(int reg){ //push reg //オペコード、レジスタ __op_format(0,(char)0x50,reg); } void op_push_value(long data){ //スタックにリテラル値をプッシュ if(-128<=data&&data<=127){ //push 8ビット値 OpBuffer[obp++]=(char)0x6A; OpBuffer[obp++]=(char)data; } else{ //push 32ビット値 OpBuffer[obp++]=(char)0x68; *((long *)(OpBuffer+obp))=data; obp+=sizeof(long); } } void op_pop(int reg){ //pop reg //オペコード、レジスタ __op_format(0,(char)0x58,reg); } void op_add_esp(int num){ //スタックポインタの加算(pop方向) //add esp,num if(0xFFFFFF80&num){ OpBuffer[obp++]=(char)0x81; OpBuffer[obp++]=(char)0xC4; *((long *)(OpBuffer+obp))=num; obp+=sizeof(long); } else{ //「128 > num > -127」の場合 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)0xC4; OpBuffer[obp++]=(char)num; } } void op_sub_esp(int num){ //スタックポインタの減算(push方向) //sub esp,num if(0xFFFFFF80&num){ OpBuffer[obp++]=(char)0x81; OpBuffer[obp++]=(char)0xEC; *((long *)(OpBuffer+obp))=num; obp+=sizeof(long); } else{ //「128 > num > -127」の場合 OpBuffer[obp++]=(char)0x83; OpBuffer[obp++]=(char)0xEC; OpBuffer[obp++]=(char)num; } } ///////////////////// // cmp関連 ///////////////////// void op_cmp_value(int op_size,int reg,char byte_data){ //cmp reg,byte_data if(op_size==sizeof(char)&®==REG_EAX){ //alレジスタの場合は特殊 OpBuffer[obp++]=(char)0x3C; //8ビット値 OpBuffer[obp++]=byte_data; return; } //16ビット演算のプリフィックス if(op_size==sizeof(short)) OpBuffer[obp++]=(char)0x66; //オペコード if(op_size==sizeof(char)) OpBuffer[obp++]=(char)0x80; else OpBuffer[obp++]=(char)0x83; //レジスタ OpBuffer[obp++]=(char)(0xF8| REGISTER_OPERAND(reg)); //8ビット値 OpBuffer[obp++]=byte_data; } void op_setne( int reg ){ //オペコード OpBuffer[obp++]=(char)0x0F; OpBuffer[obp++]=(char)0x95; //レジスタ OpBuffer[obp++]=(char)( 0xC0 | REGISTER_OPERAND(reg) ); } //////////////////// // test関連 //////////////////// void op_test(int reg1,int reg2){ //test reg1,reg2 //1000 0101 11rr rbbb OpBuffer[obp++]=(char)0x85; OpBuffer[obp++]=(char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)); } ////////////////////////////// // 浮動小数点関連 ////////////////////////////// void op_fld_ptr_esp(int type){ //スタックポインタが示すバッファのデータを浮動小数点レジスタへロード if(type==DEF_DOUBLE){ //fld qword ptr[esp] OpBuffer[obp++]=(char)0xDD; OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; } else if(type==DEF_SINGLE){ //fld dword ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; } else if(type==DEF_INT64){ //fild qword ptr[esp] OpBuffer[obp++]=(char)0xDF; OpBuffer[obp++]=(char)0x2C; OpBuffer[obp++]=(char)0x24; } else if(type==DEF_LONG){ //fild dword ptr[esp] OpBuffer[obp++]=(char)0xDB; OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; } } void op_fld_basereg(int type,int base_reg){ //fld ptr[reg] //オペコード if(type==DEF_DOUBLE) OpBuffer[obp++]=(char)0xDD; else if(type==DEF_SINGLE) OpBuffer[obp++]=(char)0xD9; else SetError(300,NULL,cp); if(base_reg==REG_ESP){ OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; } else if(base_reg==REG_EBP){ OpBuffer[obp++]=(char)0x45; OpBuffer[obp++]=(char)0x00; } else{ OpBuffer[obp++]=(char)REGISTER_OPERAND(base_reg); } } void op_fld_base_offset(int type,int base_reg,int offset){ //fld ptr[reg+offset] //オペコード if(type==DEF_DOUBLE) OpBuffer[obp++]=(char)0xDD; else if(type==DEF_SINGLE) OpBuffer[obp++]=(char)0xD9; else SetError(300,NULL,cp); //オペコード、レジスタ if(base_reg==REG_ESP){ OpBuffer[obp++]=(char)0x84; OpBuffer[obp++]=(char)0x24; } else{ OpBuffer[obp++]=(char)(0x80|REGISTER_OPERAND(base_reg)); } //オフセット値 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } void op_fld_base_offset_ex(int type,int base_reg1,int base_reg2,int offset,BOOL bUseOffset){ //fld ptr[base_reg1+base_reg2+offset] if(base_reg1==REG_ESP){ //SIBバイトのindex部にespは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //オペコード if(type==DEF_DOUBLE) OpBuffer[obp++]=(char)0xDD; else if(type==DEF_SINGLE) OpBuffer[obp++]=(char)0xD9; else SetError(300,NULL,cp); int reg=0; if(bUseOffset){ /////////////////////////// // オフセット値を使う /////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x84| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); //オフセット値 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } else{ /////////////////////////// // オフセット値を使わない /////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x04| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); } } void op_fstp_basereg(int type,int base_reg){ //fstp ptr[reg] //オペコード if(type==DEF_DOUBLE) OpBuffer[obp++]=(char)0xDD; else if(type==DEF_SINGLE) OpBuffer[obp++]=(char)0xD9; else SetError(300,NULL,cp); if(base_reg==REG_ESP){ OpBuffer[obp++]=(char)0x1C; OpBuffer[obp++]=(char)0x24; } else if(base_reg==REG_EBP){ OpBuffer[obp++]=(char)0x5D; OpBuffer[obp++]=(char)0x00; } else{ OpBuffer[obp++]=(char)(0x18|REGISTER_OPERAND(base_reg)); } } void op_fstp_base_offset(int type,int base_reg,int offset){ //fstp ptr[reg+offset] //オペコード if(type==DEF_DOUBLE) OpBuffer[obp++]=(char)0xDD; else if(type==DEF_SINGLE) OpBuffer[obp++]=(char)0xD9; else SetError(300,NULL,cp); //オペコード、レジスタ if(base_reg==REG_ESP){ OpBuffer[obp++]=(char)0x9C; OpBuffer[obp++]=(char)0x24; } else{ OpBuffer[obp++]=(char)(0x98|REGISTER_OPERAND(base_reg)); } //オフセット値 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } void op_fstp_base_offset_ex(int type,int base_reg1,int base_reg2,int offset,BOOL bUseOffset){ //fstp ptr[base_reg1+base_reg2+offset] if(base_reg1==REG_ESP){ //SIBバイトのindex部にespは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //オペコード if(type==DEF_DOUBLE) OpBuffer[obp++]=(char)0xDD; else if(type==DEF_SINGLE) OpBuffer[obp++]=(char)0xD9; else SetError(300,NULL,cp); int reg=0; if(bUseOffset){ /////////////////////////// // オフセット値を使う /////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x9C| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); //オフセット値 *((long *)(OpBuffer+obp))=offset; obp+=sizeof(long); } else{ /////////////////////////// // オフセット値を使わない /////////////////////////// //レジスタ OpBuffer[obp++]=(char)(0x1C| REGISTER_OPERAND(reg)<<3); //ベースレジスタ OpBuffer[obp++]=(char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)); } } ////////////////////////////// // レジスタ関連 ////////////////////////////// void op_zero_reg(int reg){ //レジスタに0をセット switch(reg){ case REG_EAX: //xor eax,eax OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xC0; break; case REG_EBX: //xor ebx,ebx OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xDB; break; case REG_ECX: //xor ecx,ecx OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xC9; break; case REG_EDX: //xor edx,edx OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xD2; break; case REG_EBP: //xor ebp,ebp OpBuffer[obp++]=(char)0x33; OpBuffer[obp++]=(char)0xED; break; } } void fpu_cast(){ /////////////////////// // FPUの切り捨て設定 /////////////////////// //sub esp,16 op_sub_esp(16); //mov dword ptr[esp+4],eax OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x44; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0x04; //fnstcw word ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x3C; OpBuffer[obp++]=(char)0x24; //mov ax,word ptr[esp] OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x04; OpBuffer[obp++]=(char)0x24; //or ah,0Ch OpBuffer[obp++]=(char)0x80; OpBuffer[obp++]=(char)0xCC; OpBuffer[obp++]=(char)0x0C; //mov word ptr[esp+2],ax OpBuffer[obp++]=(char)0x66; OpBuffer[obp++]=(char)0x89; OpBuffer[obp++]=(char)0x44; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0x02; //fldcw word ptr[esp+2] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x6C; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0x02; //mov eax,dword ptr[esp+4] OpBuffer[obp++]=(char)0x8B; OpBuffer[obp++]=(char)0x44; OpBuffer[obp++]=(char)0x24; OpBuffer[obp++]=(char)0x04; //add esp,16 op_add_esp(16); } void fpu_cast_end(){ //sub esp,16 op_sub_esp(16); //fldcw word ptr[esp] OpBuffer[obp++]=(char)0xD9; OpBuffer[obp++]=(char)0x2C; OpBuffer[obp++]=(char)0x24; //add esp,16 op_add_esp(16); } ///////////////////////////// // 関数呼び出し ///////////////////////////// void op_call(SUBINFO *psi){ OpBuffer[obp++]=(char)0xE8; pobj_SubAddrSchedule->add(psi,1); psi->bUse=1; obp+=sizeof(long); }