#include "IMCodeUnits.h" #include #include #include "RelocTable.h" #include "SymbolTable.h" /////////////////////////////////////////////////////////////////////////////////// // Àü¿ªº¯¼ö static char szBuffer[128]; static const char * g_szArrRegString[] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "NONE" }; static const char * g_szArrConditionString[] = { "G", "GE", "L", "LE", "E", "NE" }; static CSymbolTable * g_pSymTable = NULL; static FUNCTABLE * g_pFuncTable = NULL; static CRelocTable * g_pRelocTable = NULL; byte arrReg1[] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 }; byte arrReg2[] = { 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; byte arrReg3[] = { 0x80, 0x88, 0x90, 0x98, 0xA0, 0xA8, 0xB0, 0xB8 }; byte arrReg4[] = { 0xC0, 0xC8, 0xD0, 0xD8, 0xE0, 0xE8, 0xF0, 0xF8 }; /////////////////////////////////////////////////////////////////////////////////// // void SetSymbolTable( CSymbolTable * p ) { g_pSymTable = p; } void SetFuncTable( FUNCTABLE * p ) { g_pFuncTable = p; } void SetRelocTable( CRelocTable * p ) { g_pRelocTable = p; } /////////////////////////////////////////////////////////////////////////////////// // union Conversion { float floatValue; int intValue; byte byteValue[4]; Conversion() : intValue( 0 ) {} Conversion( int v ) : intValue( v ) {} Conversion( float f ) : floatValue( f ) {} Conversion( CONST constID, int offset ) { eDataType type = g_pSymTable->GetTypeOfConst( int(constID) ); const char * szValue = g_pSymTable->GetNameOfConst( int(constID) ); switch( type ) { case T_BOOL: if( strcmp( szValue, "true" ) == 0 ) intValue = 1; else intValue = 0; break; case T_INT: { intValue = strtol( szValue, NULL, 0 ); break; } case T_FLOAT: floatValue = (float)atof( szValue ); break; case T_STRING: g_pRelocTable->AddConstString( offset ); intValue = g_pSymTable->GetOffsetOfConst( int(constID ) ); break; } } void Set( byte * p ) { p[0] = byteValue[0]; p[1] = byteValue[1]; p[2] = byteValue[2]; p[3] = byteValue[3]; } }; /////////////////////////////////////////////////////////////////////////////////// // int Code_RM32_Offset( byte * p, byte opByte, int opDigit, int funcID, long addr, int VarOffset ) { p[0] = opByte; if( funcID == 0 ) { p[1] = arrReg1[opDigit] + 5; Conversion value( VarOffset ); value.Set( p + 2 ); g_pRelocTable->AddGlobalVar( addr + 2 ); //disp32 return 6; } else { if( VarOffset & 0xffffff00 ) { p[1] = arrReg3[opDigit] + 5; //disp32[EBP] Conversion value( VarOffset ); value.Set( p + 2 ); return 6; } else { p[1] = arrReg2[opDigit] + 5; p[2] = VarOffset & 0xff; //disp8[EBP] return 3; } } } inline int Code_RM32( byte * p, byte opByte, int opDigit, int funcID, int varID, long addr ) { int offset = g_pSymTable->GetOffsetOfVar( varID ); return Code_RM32_Offset( p, opByte, opDigit, funcID, addr, offset ); } long Code_RM32_CodeSize_Offset( int funcID, int VarOffset ) { if( funcID == 0 || VarOffset & 0xffffff00 ) return 6; else return 3; } inline long Code_RM32_CodeSize( int funcID, int varID ) { int offset = g_pSymTable->GetOffsetOfVar( int(varID) ); return Code_RM32_CodeSize_Offset( funcID, offset ); } /////////////////////////////////////////////////////////////////////////////////// // COP_call COP_call::COP_call( FUNC funcID, int line ) : m_funcID( funcID ), m_iLine( line ) {} int COP_call::ToMachineCode( byte * p ) { FUNCTABLE::iterator result = g_pFuncTable->find( int(m_funcID) ); if( result == g_pFuncTable->end() ) { WarningMessage2( m_iLine, "Á¤ÀǵÇÁö ¾ÊÀº ÇÔ¼ö¸¦ È£ÃâÇÏ·Á ½ÃµµÇß½À´Ï´Ù. : %s" , g_pSymTable->GetTypeStringOfFunc( int(m_funcID) ) ); } p[0] = 0xe8; Conversion value( result->second - (m_lAddress+5) ); value.Set( p + 1 ); return 5; } long COP_call::Addressing( long addr ) { m_lAddress = addr; return addr + 5; } void COP_call::Show( MESSAGE_FUNCTION2 Print ) { Print( "CALL\t\t%s\n", g_pSymTable->GetNameOfFunc( int(m_funcID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_mov COP_mov::COP_mov( FUNC funcID, VAR varID, eRegister reg ) : m_Type( 0 ), m_funcID( funcID ), m_leftVarID( varID ), m_midArrayIndex( 0 ), m_rightReg( reg ) {} COP_mov::COP_mov( eRegister reg, FUNC funcID, VAR varID ) : m_Type( 1 ), m_funcID( funcID ), m_leftReg( reg ), m_midArrayIndex( 0 ), m_rightVarID( varID ) {} COP_mov::COP_mov( eRegister reg, CONST constID ) : m_Type( 2 ), m_funcID( 0 ), m_leftReg( reg ), m_midArrayIndex( 0 ), m_rightConstID( constID ) {} COP_mov::COP_mov( FUNC funcID, VAR varID, float valuef ) : m_Type( 3 ), m_funcID( funcID ), m_leftVarID( varID ), m_midArrayIndex( 0 ), m_rightValuef( valuef ) {} COP_mov::COP_mov( eRegister lreg, eRegister rreg ) : m_Type( 4 ), m_funcID( 0 ), m_leftReg( lreg ), m_midArrayIndex( 0 ), m_rightReg( rreg ) {} COP_mov::COP_mov( eRegister lreg, int value ) : m_Type( 5 ), m_funcID( 0 ), m_leftReg( lreg ), m_midArrayIndex( 0 ), m_rightValue( value ) {} COP_mov::COP_mov( FUNC funcID, VAR varID, int arrayIndex, eRegister rreg ) : m_Type( 6 ), m_funcID( funcID ), m_leftVarID( varID ), m_midArrayIndex( arrayIndex ), m_rightReg( rreg ) {} COP_mov::COP_mov( eRegister lreg, FUNC funcID, VAR varID, eRegister indexReg ) : m_Type( 7 ), m_funcID( funcID ), m_leftReg( lreg ), m_midIndexReg( indexReg ), m_rightVarID( varID ) {} int COP_mov::ToMachineCode( byte * p ) { switch( m_Type ) { case 0: //89 / r MOV r/m32,r32 Move r32 to r/m32 case 6: { int VarOffset = g_pSymTable->GetOffsetOfVar( int(m_leftVarID) ) + (m_midArrayIndex*4); return Code_RM32_Offset( p, 0x89, m_rightReg, int(m_funcID), m_lAddress, VarOffset ); } case 1: //8B / r MOV r32,r/m32 Move r/m32 to r32 return Code_RM32( p, 0x8b, m_leftReg, int(m_funcID), int(m_rightVarID), m_lAddress ); case 2: //B8+ rd MOV r32,imm32 Move imm32 to r32 { p[0] = 0xb8 + m_leftReg; Conversion value( m_rightConstID, m_lAddress + 1 ); value.Set( p + 1 ); return 5; } case 3: //C7 / 0 MOV r/m32,imm32 Move imm32 to r/m32 { int codeSize = Code_RM32( p, 0xc7, 0, int(m_funcID), int(m_leftVarID), m_lAddress ); Conversion value( m_rightValuef ); value.Set( p + codeSize ); return codeSize + 4; } case 4: //89 / r MOV r/m32,r32 Move r32 to r/m32 { p[0] = 0x89; p[1] = arrReg4[m_rightReg] + m_leftReg; return 2; } case 5: //C7 / 0 MOV r/m32,imm32 Move imm32 to r/m32 { p[0] = 0xc7; p[1] = 0xc0 + m_leftReg; Conversion value( m_rightValue ); value.Set( p + 2 ); return 6; } case 7: { //IMUL m_midIndexReg, -4 //6B / r ib IMUL r32,imm8 doubleword register ¡þ doubleword register * signextended immediate byte p[0] = 0x6b; p[1] = 0xc0 + (m_midIndexReg * 9); p[2] = 0x04; int offset = g_pSymTable->GetOffsetOfVar( int(m_rightVarID) ); if( m_funcID == 0 ) { //8B / r MOV r32,r/m32 Move r/m32 to r32 p[3] = 0x8b; p[4] = arrReg3[m_leftReg] + m_midIndexReg; Conversion value( offset ); value.Set( p + 5 ); g_pRelocTable->AddGlobalVar( m_lAddress + 5 ); return 9; } else { //ADD m_midIndexReg, EBP //03 / r ADD r32,r/m32 Add r/m32 to r32 p[3] = 0x03; p[4] = arrReg4[m_midIndexReg] + 5; //8B / r MOV r32,r/m32 Move r/m32 to r32 p[5] = 0x8b; p[6] = arrReg3[m_leftReg] + m_midIndexReg; Conversion value( offset ); value.Set( p + 7 ); return 11; } break; } } return 0; } long COP_mov::Addressing( long addr ) { m_lAddress = addr; switch( m_Type ) { case 0: case 6: { int offset = g_pSymTable->GetOffsetOfVar( int(m_leftVarID) ) + (m_midArrayIndex*4); return addr + Code_RM32_CodeSize_Offset( int(m_funcID), offset ); } case 1: { int offset = g_pSymTable->GetOffsetOfVar( int(m_rightVarID) ) + (m_midArrayIndex*4); return addr + Code_RM32_CodeSize_Offset( int(m_funcID), offset ); } case 2: return addr + 5; case 3: { int offset = g_pSymTable->GetOffsetOfVar( int(m_leftVarID) ) + (m_midArrayIndex*4); return addr + 4 + Code_RM32_CodeSize_Offset( int(m_funcID), offset ); } case 4: return addr + 2; case 5: return addr + 6; case 7: return addr + ( m_funcID == 0 ? 9 : 11 ); } return 0; } void COP_mov::Show( MESSAGE_FUNCTION2 Print ) { Print( "MOV\t\t" ); switch( m_Type ) { case 0: Print( "%s, %s\n", g_pSymTable->GetNameOfVar( int(m_leftVarID) ) , g_szArrRegString[m_rightReg] ); break; case 1: Print( "%s, %s\n", g_szArrRegString[m_leftReg] , g_pSymTable->GetNameOfVar( int(m_rightVarID) ) ); break; case 2: Print( "%s, %s\n", g_szArrRegString[m_leftReg] , g_pSymTable->GetNameOfConst( int(m_rightConstID) ) ); break; case 3: Print( "%s, %f\n", g_pSymTable->GetNameOfVar( int(m_leftVarID) ) , m_rightValuef ); break; case 4: Print( "%s, %s\n", g_szArrRegString[m_leftReg] , g_szArrRegString[m_rightReg] ); break; case 5: Print( "%s, %d\n", g_szArrRegString[m_leftReg] , m_rightValue ); break; case 6: Print( "%s[%d], %s\n", g_pSymTable->GetNameOfVar( int(m_leftVarID) ) , m_midArrayIndex, g_szArrRegString[m_rightReg] ); break; case 7: Print( "%s, %s[%s]\n", g_szArrRegString[m_leftReg] , g_pSymTable->GetNameOfVar( int(m_rightVarID) ) , g_szArrRegString[m_midIndexReg] ); break; } } /////////////////////////////////////////////////////////////////////////////////// // COP_nop int COP_nop::ToMachineCode( byte * p ) { p[0] = 0x90; return 1; } long COP_nop::Addressing( long addr ) { m_lAddress = addr; return addr + 1; } void COP_nop::Show( MESSAGE_FUNCTION2 Print ) { Print( "NOP\n" ); } /////////////////////////////////////////////////////////////////////////////////// // COP_add COP_add::COP_add( eRegister reg, int value ) : m_Type( 0 ), m_leftReg( reg ), m_iValue( value ) {} COP_add::COP_add( eRegister lreg, eRegister rreg ) : m_Type( 1 ), m_leftReg( lreg ), m_rightReg( rreg ) {} int COP_add::ToMachineCode( byte * p ) { switch( m_Type ) { case 0: { //81 /0 id ADD r/m32,imm32 Add imm32 to r/m32 p[0] = 0x81; p[1] = 0xc0 + m_leftReg; Conversion value( m_iValue ); value.Set( p + 2 ); return 6; } case 1: //03 / r ADD r32,r/m32 Add r/m32 to r32 p[0] = 0x03; p[1] = arrReg4[m_leftReg] + m_rightReg; return 2; } return 0; } long COP_add::Addressing( long addr ) { m_lAddress = addr; switch( m_Type ) { case 0: return addr + 6; case 1: return addr + 2; } return 0; } void COP_add::Show( MESSAGE_FUNCTION2 Print ) { Print( "ADD\t\t" ); switch( m_Type ) { case 0: Print( "%s, %d\n", g_szArrRegString[m_leftReg], m_iValue ); break; case 1: Print( "%s, %s\n", g_szArrRegString[m_leftReg], g_szArrRegString[m_rightReg] ); break; } } /////////////////////////////////////////////////////////////////////////////////// // COP_sub COP_sub::COP_sub( eRegister reg, int value ) : m_Type( 0 ), m_leftReg( reg ), m_iValue( value ) {} COP_sub::COP_sub( eRegister lreg, eRegister rreg ) : m_Type( 1 ), m_leftReg( lreg ), m_rightReg( rreg ) {} int COP_sub::ToMachineCode( byte * p ) { switch( m_Type ) { case 0: { //81 /5 id SUB r/m32,imm32 Subtract imm32 from r/m32 p[0] = 0x81; p[1] = 0xe8 + m_leftReg; Conversion value( m_iValue ); value.Set( p + 2 ); return 6; } case 1: //2B / r SUB r32,r/m32 Subtract r/m32 from r32 p[0] = 0x2b; p[1] = arrReg4[m_leftReg] + m_rightReg; return 2; } return 0; } long COP_sub::Addressing( long addr ) { m_lAddress = addr; switch( m_Type ) { case 0: return addr + 6; case 1: return addr + 2; } return 0; } void COP_sub::Show( MESSAGE_FUNCTION2 Print ) { Print( "SUB\t\t" ); switch( m_Type ) { case 0: Print( "%s, %d\n", g_szArrRegString[m_leftReg], m_iValue ); break; case 1: Print( "%s, %s\n", g_szArrRegString[m_leftReg], g_szArrRegString[m_rightReg] ); break; } } /////////////////////////////////////////////////////////////////////////////////// // COP_imul COP_imul::COP_imul( eRegister lreg, eRegister rreg ) : m_leftReg( lreg ), m_rightReg( rreg ) {} int COP_imul::ToMachineCode( byte * p ) { //0F AF / r IMUL r32,r/m32 doubleword register <- doubleword register * r/m doubleword p[0] = 0x0f; p[1] = 0xaf; p[2] = arrReg4[m_leftReg] + m_rightReg; return 3; } long COP_imul::Addressing( long addr ) { m_lAddress = addr; return addr + 3; } void COP_imul::Show( MESSAGE_FUNCTION2 Print ) { Print( "IMUL\t\t" ); Print( "%s, %s\n", g_szArrRegString[m_leftReg], g_szArrRegString[m_rightReg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_idiv COP_idiv::COP_idiv( eRegister rreg ) : m_rightReg( rreg ) { } int COP_idiv::ToMachineCode( byte * p ) { //99 CDQ EDX:EAX ¡þ sign-extend of EAX p[0] = 0x99; //F7 /7 IDIV r/m32 Signed divide EDX:EAX (where EDX must contain sign-extension of EAX) //by r/m doubleword. (Results:EAX=Quotient, EDX=Remainder) p[1] = 0xf7; p[2] = 0xf8 + m_rightReg; return 3; } long COP_idiv::Addressing( long addr ) { m_lAddress = addr; return addr + 3; } void COP_idiv::Show( MESSAGE_FUNCTION2 Print ) { Print( "IDIV\t\t" ); Print( "%s\n", g_szArrRegString[m_rightReg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_push COP_push::COP_push( eRegister reg ) : m_Reg( reg ) {} int COP_push::ToMachineCode( byte * p ) { p[0] = 0x50 + m_Reg; return 1; } long COP_push::Addressing( long addr ) { m_lAddress = addr; return addr + 1; } void COP_push::Show( MESSAGE_FUNCTION2 Print ) { Print( "PUSH\t\t%s\n", g_szArrRegString[m_Reg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_pop COP_pop::COP_pop( eRegister reg ) : m_Reg( reg ) {} int COP_pop::ToMachineCode( byte * p ) { p[0] = 0x58 + m_Reg; //58+ rd POP r32 Pop top of stack into r32; increment stack pointer return 1; } long COP_pop::Addressing( long addr ) { m_lAddress = addr; return addr + 1; } void COP_pop::Show( MESSAGE_FUNCTION2 Print ) { Print( "POP\t\t%s\n", g_szArrRegString[m_Reg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_jmp COP_jmp::COP_jmp() : m_pJumpTarget( 0 ) { } COP_jmp::COP_jmp( IOPCode * pJmpTarget ) : m_pJumpTarget( pJmpTarget ) { } COP_jmp::~COP_jmp() { } int COP_jmp::ToMachineCode( byte * p ) { //E9 cd JMP rel32 Jump near, relative, displacement relative to next instruction p[0] = 0xe9; Conversion i = m_pJumpTarget->m_lAddress - ( m_lAddress + 5 ); i.Set( p + 1 ); return 5; } long COP_jmp::Addressing( long addr ) { m_lAddress = addr; return addr + 5; } void COP_jmp::Show( MESSAGE_FUNCTION2 Print ) { Print( "JMP\t\t%X\n", m_pJumpTarget->m_lAddress ); } /////////////////////////////////////////////////////////////////////////////////// // COP_jcc COP_jcc::COP_jcc( eCondition condition ) : m_Condition( condition ) {} int COP_jcc::ToMachineCode( byte * p ) { p[0] = 0x0f; Conversion i = m_pJumpTarget->m_lAddress - ( m_lAddress + 6 ); i.Set( p + 2 ); //¸ðµÎ relative Á¡ÇÁÀÓ switch( m_Condition ) { case G: //0F 8F cw/cd JG rel16/32 Jump near if greater (ZF=0 and SF=OF) p[1] = 0x8f; break; case GE: //0F 8D cw/cd JGE rel16/32 Jump near if greater or equal (SF=OF) p[1] = 0x8d; break; case L: //0F 8C cw/cd JL rel16/32 Jump near if less (SF<>OF) p[1] = 0x8c; break; case LE: //0F 8E cw/cd JLE rel16/32 Jump near if less or equal (ZF=1 or SF<>OF) p[1] = 0x8e; break; case E: //0F 84 cw/cd JE rel16/32 Jump near if equal (ZF=1) p[1] = 0x84; break; case NE: //0F 85 cw/cd JNE rel16/32 Jump near if not equal (ZF=0) p[1] = 0x85; break; } return 6; } long COP_jcc::Addressing( long addr ) { m_lAddress = addr; return addr + 6; } void COP_jcc::Show( MESSAGE_FUNCTION2 Print ) { Print( "J%s\t\t%X\n", g_szArrConditionString[m_Condition], m_pJumpTarget->m_lAddress ); } /////////////////////////////////////////////////////////////////////////////////// // COP_jmpmark COP_jmpmark::COP_jmpmark() : m_pJumpSrc( 0 ) {} COP_jmpmark::COP_jmpmark( COP_jmp * pOPjmp ) : m_pJumpSrc( pOPjmp ) { pOPjmp->m_pJumpTarget = this; } int COP_jmpmark::ToMachineCode( byte * ) { //Äڵ带 ¸¸µéÁö ¾ÊÀ½. return 0; } long COP_jmpmark::Addressing( long addr ) { m_lAddress = addr; //ÁÖ¼Ò¸¦ Áõ°¡½ÃŰÁö ¾ÊÀ½À¸·Î½á ´ÙÀ½ instruction°ú °°Àº ÁÖ¼Ò¸¦ °¡Áü. return addr; } void COP_jmpmark::Show( MESSAGE_FUNCTION2 Print ) { if( m_pJumpSrc ) Print( "JMPMARK\t\t%X\n", m_pJumpSrc->m_lAddress ); else Print( "JMPMARK\t\t\n" ); } /////////////////////////////////////////////////////////////////////////////////// // COP_cmp COP_cmp::COP_cmp( FUNC funcID, VAR lvarID, CONST rconstID ) : m_Type( 0 ), m_funcID( funcID ), m_leftVarID( lvarID ), m_rightConstID( rconstID ) {} COP_cmp::COP_cmp( eRegister lreg, byte value ) : m_Type( 1 ), m_funcID( 0 ), m_leftReg( lreg ), m_rightValue( value ) {} COP_cmp::COP_cmp( eRegister lreg, eRegister rreg ) : m_Type( 2 ), m_funcID( 0 ), m_leftReg( lreg ), m_rightReg( rreg ) {} int COP_cmp::ToMachineCode( byte * p ) { switch( m_Type ) { case 0: { p[0] = 0x81; int offset = g_pSymTable->GetOffsetOfVar( int(m_leftVarID) ); if( m_funcID == 0 ) { p[1] = 0x3d; Conversion value( offset ); value.Set( p + 2 ); g_pRelocTable->AddGlobalVar( m_lAddress + 2 ); Conversion value2( m_rightConstID, m_lAddress + 6 ); value2.Set( p + 6 ); return 10; } else { if( offset & 0xffffff00 ) { p[1] = 0xbd; Conversion value( offset ); value.Set( p + 2 ); Conversion value2( m_rightConstID, m_lAddress + 6 ); value2.Set( p + 6 ); return 10; } else { p[1] = 0x7d; p[2] = offset & 0xff; Conversion value2( m_rightConstID, m_lAddress + 3 ); value2.Set( p + 3 ); return 7; } } break; } case 1: //83 /7 ib CMP r/m32,imm8 Compare imm8 with r/m32 p[0] = 0x83; p[1] = 0xf8 + m_leftReg; p[2] = m_rightValue; return 3; case 2: //3B / r CMP r32,r/m32 Compare r/m32 with r32 p[0] = 0x3b; p[1] = arrReg4[m_leftReg] + m_rightReg; return 2; } return 0; } long COP_cmp::Addressing( long addr ) { m_lAddress = addr; switch( m_Type ) { case 0: { int offset = g_pSymTable->GetOffsetOfVar( int(m_leftVarID) ); if( m_funcID == 0 || offset & 0xffffff00 ) return addr + 10; else return addr + 7; break; } case 1: return addr + 3; case 2: return addr + 2; } return 0; } void COP_cmp::Show( MESSAGE_FUNCTION2 Print ) { switch( m_Type ) { case 0: Print( "CMP\t\t%s, %s\n", g_pSymTable->GetNameOfVar( int(m_leftVarID) ) , g_pSymTable->GetNameOfConst( int(m_rightConstID) ) ); break; case 1: Print( "CMP\t\t%s, %d\n", g_szArrRegString[m_leftReg], m_rightValue ); break; case 2: Print( "CMP\t\t%s, %s\n", g_szArrRegString[m_leftReg], g_szArrRegString[m_rightReg] ); break; } } /////////////////////////////////////////////////////////////////////////////////// // COP_ret int COP_ret::ToMachineCode( byte * p ) { //C3 RET Near return to calling procedure p[0] = 0xc3; return 1; } long COP_ret::Addressing( long addr ) { m_lAddress = addr; return addr + 1; } void COP_ret::Show( MESSAGE_FUNCTION2 Print ) { Print( "RET\n" ); } /////////////////////////////////////////////////////////////////////////////////// // COP_xor COP_xor::COP_xor( eRegister lreg, eRegister rreg ) : m_leftReg( lreg ), m_rightReg( rreg ) {} int COP_xor::ToMachineCode( byte * p ) { //33 / r XOR r32,r/m32 r8 XOR r/m8 p[0] = 0x33; p[1] = arrReg4[m_leftReg] + m_rightReg; return 2; } long COP_xor::Addressing( long addr ) { m_lAddress = addr; return addr + 2; } void COP_xor::Show( MESSAGE_FUNCTION2 Print ) { Print( "XOR\t\t%s, %s\n", g_szArrRegString[m_leftReg], g_szArrRegString[m_rightReg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_setcc COP_setcc::COP_setcc( eCondition condition, eRegister lreg ) : m_Condition( condition ), m_Reg( lreg ) { if( m_Reg > EBX ) ScriptSystemError( "setcc ¸í·É¿¡ EAX, ECX, EDX, EBX¿ÜÀÇ ·¹Áö½ºÅ͸¦ ÁöÁ¤Çß½À´Ï´Ù." ); } int COP_setcc::ToMachineCode( byte * p ) { //xor reg, reg¸¦ ¾²¸é EFLAG ·¹Áö½ºÅÍ °ªÀ» ¹Ù²ã¹ö¸®¹Ç·Î ¾²¸é ¾ÈµÊ. //B8+ rd MOV r32,imm32 Move imm32 to r32 p[0] = 0xb8 + m_Reg; Conversion value( 0 ); value.Set( p + 1 ); //setcc r/m8 p[5] = 0x0f; switch( m_Condition ) { case G: //0F 9F SETG r/m8 Set byte if greater (ZF=0 and SF=OF) p[6] = 0x9f; break; case GE: //0F 9D SETGE r/m8 Set byte if greater or equal (SF=OF) p[6] = 0x9d; break; case L: //0F 9C SETL r/m8 Set byte if less (SF<>OF) p[6] = 0x9c; break; case LE: //0F 9E SETLE r/m8 Set byte if less or equal (ZF=1 or SF<>OF) p[6] = 0x9e; break; case E: //0F 94 SETE r/m8 Set byte if equal (ZF=1) p[6] = 0x94; break; case NE: //0F 95 SETNE r/m8 Set byte if not equal (ZF=0) p[6] = 0x95; break; } p[7] = 0xc0 + m_Reg; return 8; } long COP_setcc::Addressing( long addr ) { m_lAddress = addr; return addr + 8; } void COP_setcc::Show( MESSAGE_FUNCTION2 Print ) { Print( "SET%s\t\t%s\n", g_szArrConditionString[m_Condition], g_szArrRegString[m_Reg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_int3 int COP_int3::ToMachineCode( byte * p ) { p[0] = 0xcc; return 1; } long COP_int3::Addressing( long addr ) { m_lAddress = addr; return addr + 1; } void COP_int3::Show( MESSAGE_FUNCTION2 Print ) { Print( "INT\t\t3\n" ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fld::COP_fld( FUNC funcID, VAR varID ) : m_funcID( funcID ), m_varID( varID ) {} int COP_fld::ToMachineCode( byte * p ) { //D9 /0 FLD m32real Push m32real onto the FPU register stack. return Code_RM32( p, 0xd9, 0, int(m_funcID), int(m_varID), m_lAddress ); } long COP_fld::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fld::Show( MESSAGE_FUNCTION2 Print ) { Print( "FLD\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fadd::COP_fadd( FUNC funcID, VAR varID ) : m_funcID( funcID ), m_varID( varID ) {} int COP_fadd::ToMachineCode( byte * p ) { //D8 /0 FADD m32 real Add m32real to ST(0) and store result in ST(0) return Code_RM32( p, 0xd8, 0, int(m_funcID), int(m_varID), m_lAddress ); } long COP_fadd::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fadd::Show( MESSAGE_FUNCTION2 Print ) { Print( "FADD\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fsub::COP_fsub( FUNC funcID, VAR varID ) : m_funcID( funcID ), m_varID( varID ) {} int COP_fsub::ToMachineCode( byte * p ) { //D8 /4 FSUB m32real Subtract m32real from ST(0) and store result in ST(0) return Code_RM32( p, 0xd8, 4, int(m_funcID), int(m_varID), m_lAddress ); } long COP_fsub::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fsub::Show( MESSAGE_FUNCTION2 Print ) { Print( "FSUB\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fmul::COP_fmul( FUNC funcID, VAR varID ) : m_funcID( funcID ), m_varID( varID ) {} int COP_fmul::ToMachineCode( byte * p ) { //D8 /1 FMUL m32real Multiply ST(0) by m32real and store result in ST(0) return Code_RM32( p, 0xd8, 1, int(m_funcID), int(m_varID), m_lAddress ); } long COP_fmul::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fmul::Show( MESSAGE_FUNCTION2 Print ) { Print( "FMUL\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fdiv::COP_fdiv( FUNC funcID, VAR varID ) : m_funcID( funcID), m_varID( varID ) {} int COP_fdiv::ToMachineCode( byte * p ) { //D8 /6 FDIV m32real Divide ST(0) by m32real and store result in ST(0) return Code_RM32( p, 0xd8, 6, int(m_funcID), int(m_varID), m_lAddress ); } long COP_fdiv::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fdiv::Show( MESSAGE_FUNCTION2 Print ) { Print( "FDIV\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fstp::COP_fstp( FUNC funcID, VAR varID, bool bDouble ) : m_funcID( funcID ), m_varID( varID ), m_bDouble( bDouble ) {} int COP_fstp::ToMachineCode( byte * p ) { if( m_bDouble ) { //DD /3 FSTP m64real Copy ST(0) to m64real and pop register stack int offset = g_pSymTable->GetOffsetOfVar( int(m_varID) ); return Code_RM32_Offset( p, 0xdd, 3, int(m_funcID), m_lAddress, offset - 4 ); } else { //D9 /3 FSTP m32real Copy ST(0) to m32real and pop register stack return Code_RM32( p, 0xd9, 3, int(m_funcID), int(m_varID), m_lAddress ); } } long COP_fstp::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fstp::Show( MESSAGE_FUNCTION2 Print ) { Print( "FSTP\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_fcomp::COP_fcomp( FUNC funcID, VAR varID ) : m_funcID( funcID ), m_varID( varID ) {} int COP_fcomp::ToMachineCode( byte * p ) { //D8 /3 FCOMP m32real Compare ST(0) with m32real and pop register stack. return Code_RM32( p, 0xd8, 3, int(m_funcID), int(m_varID), m_lAddress ); } long COP_fcomp::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); } void COP_fcomp::Show( MESSAGE_FUNCTION2 Print ) { Print( "FCOMP\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // int COP_fnstsw_ax::ToMachineCode( byte * p ) { p[0] = 0xdf; p[1] = 0xe0; return 2; } long COP_fnstsw_ax::Addressing( long addr ) { m_lAddress = addr; return addr + 2; } void COP_fnstsw_ax::Show( MESSAGE_FUNCTION2 Print ) { Print( "FNSTSW\t\tAX\n" ); } /////////////////////////////////////////////////////////////////////////////////// // COP_test_ah::COP_test_ah( byte Value8 ) : m_Value8( Value8 ) {} int COP_test_ah::ToMachineCode( byte * p ) { //F6 /0 ib TEST r/m8,imm8 AND imm8 with r/m8; set SF, ZF, PF according to result p[0] = 0xf6; p[1] = 0xc4; p[2] = m_Value8; return 3; } long COP_test_ah::Addressing( long addr ) { m_lAddress = addr; return addr + 3; } void COP_test_ah::Show( MESSAGE_FUNCTION2 Print ) { Print( "TEST\t\tAH, %d\n", m_Value8 ); } /////////////////////////////////////////////////////////////////////////////////// // COP_itoa::COP_itoa( eRegister leftReg, VAR stringBuffer ) : m_leftReg( leftReg ), m_StringBuffer( stringBuffer ) {} int COP_itoa::ToMachineCode( byte * p ) { //itoaÀÇ ¼¼¹øÂ° ÀÎÀÚ(10) push p[0] = 0x6a; //6A PUSH imm8 Push imm8 p[1] = 0x0a; //itoaÀÇ µÎ¹øÂ° ÀÎÀÚ(¹®ÀÚ¿­ ¹öÆÛ) push p[2] = 0xff; //FF /6 PUSH r/m32 Push r/m32 p[3] = 0x35; if( g_pSymTable->GetTypeOfVar( int(m_StringBuffer) ) != T_STRING ) ScriptSystemError( "À̰ÍÀº String Buffer°¡ ¾Æ´ÏÀÚ³ª??!! ( COP_itoa::ToMachineCode() )" ); int StrBufOffset = g_pSymTable->GetOffsetOfVar( int(m_StringBuffer) ); Conversion value( StrBufOffset ); g_pRelocTable->AddGlobalVar( m_lAddress + 4 ); value.Set( p + 4 ); //itoaÀÇ Ã¹¹øÂ° ÀÎÀÚ(Á¤¼ö) push p[8] = 0x50 + m_leftReg; //50+ rd PUSH r32 Push r32 //call itoa p[9] = 0xb8 + m_leftReg; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_ITOA, m_lAddress + 10 ); Conversion value2( 0 ); value.Set( p + 10 ); p[14] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[15] = 0xd0 + m_leftReg; //add esp, 12 p[16] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[17] = 0xc4; p[18] = 0x0c; return 19; } long COP_itoa::Addressing( long addr ) { m_lAddress = addr; return addr + 19; } void COP_itoa::Show( MESSAGE_FUNCTION2 Print ) { Print( "ITOA\t\t%s, %s\n", g_szArrRegString[m_leftReg] , g_pSymTable->GetNameOfConst( int(m_StringBuffer) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_ftoa::COP_ftoa( eRegister freeReg, VAR DoubleVar, VAR stringBuffer ) : m_freeReg( freeReg ), m_DoubleVar( DoubleVar ), m_StringBuffer( stringBuffer ) {} int COP_ftoa::ToMachineCode( byte * p ) { int n = 0; //gvctÀÇ ¼¼ ¹øÂ° ÀÎÀÚ(¹®ÀÚ¿­ ¹öÆÛ) push p[n++] = 0xff; //FF /6 PUSH r/m32 Push r/m32 p[n++] = 0x35; if( g_pSymTable->GetTypeOfVar( int(m_StringBuffer) ) != T_STRING ) ScriptSystemError( "À̰ÍÀº String Buffer°¡ ¾Æ´ÏÀÚ³ª??!! ( COP_ftoa::ToMachineCode() )" ); int StrBufOffset = g_pSymTable->GetOffsetOfVar( int(m_StringBuffer) ); Conversion value( StrBufOffset ); g_pRelocTable->AddGlobalVar( m_lAddress + n ); value.Set( p + n ); n += 4; //gvctÀÇ µÎ ¹øÂ° ÀÎÀÚ(À¯È¿ ¼ýÀÚ) push p[n++] = 0x6a; //6A PUSH imm8 Push imm8 p[n++] = 0x08; //À¯È¿ ¼ýÀÚ¸¦ 15·Î ¼³Á¤. //gvctÀÇ Ã¹ ¹øÂ° ÀÎÀÚ(½Ç¼ö°ª) push -- doubleÀ» ÀÎÀÚ·Î ¹ÞÀ¸¹Ç·Î µÎ¹ø pushÇÔ. //FF /6 PUSH r/m32 Push r/m32 n += Code_RM32( p + n, 0xff, 6, 0, int(m_DoubleVar), m_lAddress + n ); int offset = g_pSymTable->GetOffsetOfVar( int(m_DoubleVar) ); n += Code_RM32_Offset( p + n, 0xff, 6, 0, m_lAddress + n, offset - 4 ); //call gvct p[n++] = 0xb8 + m_freeReg; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_GCVT, m_lAddress + n ); Conversion value2( 0 ); value2.Set( p + n ); n += 4; p[n++] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[n++] = 0xd0 + m_freeReg; //add esp, 16 p[n++] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[n++] = 0xc4; p[n++] = 0x10; return n; } long COP_ftoa::Addressing( long addr ) { m_lAddress = addr; return addr + Code_RM32_CodeSize( 0, int(m_DoubleVar) ) * 2 + 18; } void COP_ftoa::Show( MESSAGE_FUNCTION2 Print ) { Print( "FTOA\t\t%s, %s\n", g_pSymTable->GetNameOfVar( int(m_DoubleVar) ) , g_pSymTable->GetNameOfVar( int(m_StringBuffer) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_malloc::COP_malloc( eRegister reg ) : m_Reg( reg ) {} int COP_malloc::ToMachineCode( byte * p ) { for( int i = 0; i < 24; i++ ) { p[i] = 0x90; } //mallocÀÇ Ã¹¹øÂ° ÀÎÀÚ(ÇÒ´çÇÒ ¾ç) push p[0] = 0x50 + m_Reg; //50+ rd PUSH r32 Push r32 //call malloc p[1] = 0xb8 + m_Reg; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_MALLOC, m_lAddress + 2 ); Conversion value( 0 ); value.Set( p + 2 ); p[6] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[7] = 0xd0 + m_Reg; //add esp, 4 p[8] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[9] = 0xc4; p[10] = 0x04; p[11] = 0x50 + EAX; //RegisterAllocatedMemory È£Ãâ p[12] = 0x50 + ESI; //push ESI p[13] = 0x50 + EAX; //push EAX p[14] = 0xb8 + ESI; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_REGISTERALLOCATEDMEMORY, m_lAddress + 15 ); p[19] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[20] = 0xd0 + ESI; p[21] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[22] = 0xc4; //add esp, 4 p[23] = 0x04; p[24] = 0x58 + ESI; //pop ESI p[25] = 0x58 + EAX; //58+ rd POP r32 Pop top of stack into r32; increment stack pointer return 26; } long COP_malloc::Addressing( long addr ) { m_lAddress = addr; return addr + 26; } void COP_malloc::Show( MESSAGE_FUNCTION2 Print ) { Print( "MALLOC\t\t%s\n", g_szArrRegString[m_Reg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_free::COP_free( FUNC funcID, VAR varID ) : m_funcID( funcID ), m_varID( varID ) {} int COP_free::ToMachineCode( byte * p ) { //freeÀÇ Ã¹¹øÂ° ÀÎÀÚ(¸Þ¸ð¸® ÁÖ¼Ò) push //FF /6 PUSH r/m32 Push r/m32 int n = Code_RM32( p, 0xff, 6, int(m_funcID), int(m_varID), m_lAddress ); //call free p[n++] = 0xb8 + ECX; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_FREE, m_lAddress + n ); Conversion value( 0 ); value.Set( p + n ); n += 4; p[n++] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[n++] = 0xd0 + ECX; //add esp, 4 p[n++] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[n++] = 0xc4; p[n++] = 0x04; //UnregisterAllocatedMemory È£Ãâ n += Code_RM32( p + n, 0xff, 6, int(m_funcID), int(m_varID), m_lAddress + n ); p[n++] = 0xb8 + ECX; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_UNREGISTERALLOCATEDMEMORY, m_lAddress + n ); n += 4; p[n++] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[n++] = 0xd0 + ECX; p[n++] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[n++] = 0xc4; p[n++] = 0x04; return n; } long COP_free::Addressing( long addr ) { int n = Code_RM32_CodeSize( int(m_funcID), int(m_varID) ); m_lAddress = addr; return addr + ((n + 10)*2); } void COP_free::Show( MESSAGE_FUNCTION2 Print ) { Print( "FREE\t\t%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_strcpy::COP_strcpy( eRegister lreg, eRegister rreg ) : m_type( 0 ), m_leftReg( lreg ), m_rightReg( rreg ) {} COP_strcpy::COP_strcpy( eRegister lreg, FUNC funcID, VAR varID ) : m_type( 1 ), m_leftReg( lreg ), m_funcID( funcID ), m_varID( varID ) {} int COP_strcpy::ToMachineCode( byte * p ) { int n = 0; //strcpyÀÇ µÎ¹øÂ° ÀÎÀÚ(¿øº» ¹®ÀÚ¿­ÁÖ¼Ò) push if( m_type == 0 ) { //50+ rd PUSH r32 Push r32 p[n++] = 0x50 + m_rightReg; } else { //FF /6 PUSH r/m32 Push r/m32 n += Code_RM32( p, 0xff, 6, int(m_funcID), int(m_varID), m_lAddress ); } //strcpyÀÇ Ã¹¹øÂ° ÀÎÀÚ(´ë»ó ¹®ÀÚ¿­ ÁÖ¼Ò) push p[n++] = 0x50 + m_leftReg; //call strcpy p[n++] = 0xb8 + m_leftReg; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_STRCPY, m_lAddress + n ); Conversion value( 0 ); value.Set( p + n ); n += 4; p[n++] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[n++] = 0xd0 + m_leftReg; //add esp, 8 p[n++] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[n++] = 0xc4; p[n++] = 0x08; return n; } long COP_strcpy::Addressing( long addr ) { m_lAddress = addr; if( m_type == 0 ) return addr + 12; else return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ) + 11; } void COP_strcpy::Show( MESSAGE_FUNCTION2 Print ) { Print( "STRCPY\t\t%s,", g_szArrRegString[m_leftReg] ); if( m_type == 0 ) Print( " %s\n", g_szArrRegString[m_rightReg] ); else Print( " %s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } /////////////////////////////////////////////////////////////////////////////////// // COP_strcmp::COP_strcmp( eRegister lreg, eRegister rreg ) : m_leftReg( lreg ), m_rightReg( rreg ) {} int COP_strcmp::ToMachineCode( byte * p ) { //strcmpÀÇ µÎ¹øÂ° ÀÎÀÚ push p[0] = 0x50 + m_rightReg; //50+ rd PUSH r32 Push r32 //strcmpÀÇ Ã¹¹øÂ° ÀÎÀÚ push p[1] = 0x50 + m_leftReg; //50+ rd PUSH r32 Push r32 //call strcmp p[2] = 0xb8 + m_leftReg; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_STRCMP, m_lAddress + 3 ); Conversion value( 0 ); value.Set( p + 3 ); p[7] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[8] = 0xd0 + m_leftReg; //add esp, 8 p[9] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[10] = 0xc4; p[11] = 0x08; return 12; } long COP_strcmp::Addressing( long addr ) { m_lAddress = addr; return addr + 12; } void COP_strcmp::Show( MESSAGE_FUNCTION2 Print ) { Print( "STRCMP\t\t%s, %s\n", g_szArrRegString[m_leftReg], g_szArrRegString[m_rightReg] ); } /////////////////////////////////////////////////////////////////////////////////// // COP_strlen::COP_strlen( eRegister reg ) : m_type( 0 ), m_Reg( reg ) {} COP_strlen::COP_strlen( FUNC funcID, VAR varID ) : m_type( 1 ), m_funcID( funcID ), m_varID( varID ) {} int COP_strlen::ToMachineCode( byte * p ) { //strcpyÀÇ Ã¹¹øÂ° ÀÎÀÚ(¹®ÀÚ¿­ÀÇ ÁÖ¼Ò) push int n = 0; if( m_type == 0 ) { //50+ rd PUSH r32 Push r32 p[n++] = 0x50 + m_Reg; } else { //FF /6 PUSH r/m32 Push r/m32 n += Code_RM32( p, 0xff, 6, int(m_funcID), int(m_varID), m_lAddress ); } //call strlen p[n++] = 0xb8 + EAX; //B8+ rd MOV r32,imm32 Move imm32 to r32 g_pRelocTable->AddFuncBind( FUNC_STRLEN, m_lAddress + n ); Conversion value( 0 ); value.Set( p + n ); n += 4; p[n++] = 0xff; //FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32 p[n++] = 0xd0 + EAX; //add esp, 4 p[n++] = 0x83; //83 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m32 p[n++] = 0xc4; p[n++] = 0x04; return n; } long COP_strlen::Addressing( long addr ) { m_lAddress = addr; if( m_type == 0 ) return addr + 11; else return addr + Code_RM32_CodeSize( int(m_funcID), int(m_varID) ) + 10; } void COP_strlen::Show( MESSAGE_FUNCTION2 Print ) { Print( "STRLEN\t\t" ); if( m_type == 0 ) Print( "%s\n", g_szArrRegString[m_Reg] ); else Print( "%s\n", g_pSymTable->GetNameOfVar( int(m_varID) ) ); } ///////////////////////////////////////////////////////////////////////////////////