第二步:利用我自己的汇编编译器把第一步生成的asm文件编译成自定义格式的可执行文件
第三步:把第二步生成的可执行文件加载到我的虚拟机中运行。(虚拟机可以是程序的一部分,也可以是单独的程序)
如果虚拟机是程序的一部分,然后利用代码隐藏掉编译的过程,那么这个东西看起来就像是直接执行.c 和.cpp文件。
编译出来的二进制文件现在已经可以在
windows,linux,NDS,GBA等平台上运行
前提是首先在这些平台上移植我上面贴的虚拟机。
《自己动手写操作系统》和《虚拟机的设计与实现》。C和C++解释器的项目也有几个,名字记不得了。
show 一些虚拟机的代码
#include "stdafx.h"
#include "Vm.h"
#include "misc.h"
#include "enums.h"
#include "reg.h"
#include "asmmisc.h"
//#define _STEP
//#define _DEASM
//#define _PRTREG
#define FLAG_BIT_CF 0
#define FLAG_BIT_PF 2
#define FLAG_BIT_AF 4
#define FLAG_BIT_ZF 6
#define FLAG_BIT_SF 7
#define FLAG_BIT_TF 8
#define FLAG_BIT_IF 9
#define FLAG_BIT_DF 10
#define FLAG_BIT_OF 11
#define FLAG_BIT_NF 14
#define FLAG_BIT_RF 16
#define FLAG_BIT_VM 17
#define FLAG_BIT_AC 18
#define FPU_STATUS_BIT_C0 8
#define FPU_STATUS_BIT_C1 9
#define FPU_STATUS_BIT_C2 10
#define FPU_STATUS_BIT_C3 14
int CVm::do_mov()
{
_RegVal val,opnd2;
int ret;
ret = this->GetOpnd_Common(0,&val,1);
this->GetOpnd2(&opnd2);
this->SetDesOpnd1Val(ret,&val,&opnd2);
return OK;
}
int CVm::do_push()
{
_RegVal val;
int bytes;
bytes = this->GetOpnd1(&val);
ASSERT(bytes == 4);
this->PushDWord(val.val_32);
return OK;
}
int CVm::do_pop()
{
_RegVal val,r;
int bytes;
bytes = this->GetOpnd_Common(0,&val,1);
r.val_64 = this->PopDWord();
this->SetDesOpnd1Val(bytes,&val,&r);
return OK;
}
int CVm::do_call()
{
_RegVal val;
this->GetOpnd1(&val);
this->PushDWord(this->GetEIP());
this->SetEIP(val.val_32);
return OK;
}
int CVm::do_lea()
{
int type;
_RegVal val,addr2;
type = this->GetOpnd_Common(0,&val,1);
this->GetOpnd_Common(1,&addr2,1); //lea 需要传送地址
this->SetDesOpnd1Val(type,&val,&addr2);
return OK;
}
int CVm::do_ret()
{
_RegVal opnd1;
long eip;
eip = this->PopDWord();
if(this->GetCurOpndNum() == 1)
{
this->GetOpnd1(&opnd1);
//调整堆栈
this->reg_index[REG_ESP]->val.val_32 += opnd1.val_32;
}
this->SetEIP(eip);
return OK;
}
int CVm::do_test()
{
_RegVal opnd1,opnd2,result;
this->GetOpnd1(&opnd1);
this->GetOpnd2(&opnd2);
result.val_32 = opnd1.val_32 & opnd2.val_32;
this->SetFlagBit(FLAG_BIT_ZF,result.val_32 == 0);
this->SetFlagBit(FLAG_BIT_SF,(int)(result.val_32) < 0);
this->SetFlagBit(FLAG_BIT_CF,0);
this->SetFlagBit(FLAG_BIT_OF,0);
return OK;
}
以下是其他类似的函数,主要是模拟每一个386指令
......................
inline int CVm::SetFlagBit(int bit_index,BOOL onebit)
{
if(onebit)
this->reg_index[REG_FLAG]->val.val_32 |= (1<<bit_index);
else
this->reg_index[REG_FLAG]->val.val_32 &= (~(1<<bit_index));
return OK;
}
inline int CVm::GetFlagBit(int bit_index)
{
return ((this->reg_index[REG_FLAG]->val.val_32) >> bit_index) & 0x01;
}
int CVm::ExeOper()
{
int oper = *((WORD*)(this->cur_oper));
switch(oper)
{
case OPER_ADC:do_adc();break;
case OPER_ADD:do_add();break;
case OPER_AND:do_and();break;
case OPER_CALL:do_call();break;
case OPER_CDQ:do_cdq();break;
case OPER_CMP:do_cmp();break;
case OPER_CMPSB:do_cmpsb();break;
case OPER_CMPSD:do_cmpsd();break;
case OPER_CMPSW:do_cmpsw();break;
case OPER_DEC:do_dec();break;
case OPER_DIV:do_div();break;
case OPER_FADD:do_fadd();break;
case OPER_FCOS:do_fcos();break;
case OPER_FILD:do_fild();break;
case OPER_FLD:do_fld();break;
case OPER_FMUL:do_fmul();break;
case OPER_FSIN:do_fsin();break;
case OPER_FST:do_fst();break;
case OPER_FSTP:do_fstp();break;
case OPER_FSUB:do_fsub();break;
case OPER_FXCH:do_fxch();break;
case OPER_IDIV:do_idiv();break;
case OPER_IMUL:do_imul();break;
case OPER_INC:do_inc();break;
case OPER_INT:do_int();break;
case OPER_JA:do_ja();break;
case OPER_JB:do_jb();break;
case OPER_JBE:do_jbe();break;
case OPER_JE:do_je();break;
case OPER_JG:do_jg();break;
case OPER_JGE:do_jge();break;
case OPER_JL:do_jl();break;
case OPER_JLE:do_jle();break;
case OPER_JMP:do_jmp();break;
case OPER_JNE:do_jne();break;
case OPER_JNS:do_jns();break;
case OPER_JS:do_js();break;
case OPER_LEA:do_lea();break;
case OPER_MOV:do_mov();break;
case OPER_MOVSB:do_movsb();break;
case OPER_MOVSD:do_movsd();break;
case OPER_MOVSW:do_movsw();break;
case OPER_MOVSX:do_movsx();break;
case OPER_MUL:do_mul();break;
case OPER_MYADD:do_myadd();break;
case OPER_MYDIV:do_mydiv();break;
case OPER_MYMUL:do_mymul();break;
case OPER_MYSUB:do_mysub();break;
case OPER_NEG:do_neg();break;
case OPER_NOT:do_not();break;
case OPER_NPAD:do_npad();break;
case OPER_OR:do_or();break;
case OPER_POP:do_pop();break;
case OPER_PUSH:do_push();break;
case OPER_REP:do_rep();break;
case OPER_REPNE:do_repne();break;
case OPER_RET:do_ret();break;
case OPER_SAR:do_sar();break;
case OPER_SBB:do_sbb();break;
case OPER_SCASB:do_scasb();break;
case OPER_SCASD:do_scasd();break;
case OPER_SCASW:do_scasw();break;
case OPER_SETE:do_sete();break;
case OPER_SETG:do_setg();break;
case OPER_SETGE:do_setge();break;
case OPER_SETL:do_setl();break;
case OPER_SETLE:do_setle();break;
case OPER_SETNE:do_setne();break;
case OPER_SHL:do_shl();break;
case OPER_SHR:do_shr();break;
case OPER_STOSB:do_stosb();break;
case OPER_STOSD:do_stosd();break;
case OPER_STOSW:do_stosw();break;
case OPER_SUB:do_sub();break;
case OPER_TEST:do_test();break;
case OPER_XOR:do_xor();break;
case OPER_JAE:do_jae();break;
case OPER_FSUBR:do_fsubr();break;
case OPER_FDIV:do_fdiv();break;
case OPER_FADDP:do_faddp();break;
case OPER_FDIVR:do_fdivr();break;
case OPER_FIADD:do_fiadd();break;
case OPER_FMULP:do_fmulp();break;
case OPER_FSUBP:do_fsubp();break;
case OPER_FISUB:do_fisub();break;
case OPER_FISUBR:do_fisubr();break;
case OPER_FIMUL:do_fimul();break;
case OPER_FSUBRP:do_fsubrp();break;
case OPER_FCHS:do_fchs();break;
case OPER_FABS:do_fabs();break;
case OPER_FDIVP:do_fdivp();break;
case OPER_FIDIV:do_fidiv();break;
case OPER_FIDIVR:do_fidivr();break;
case OPER_FDIVRP:do_fdivrp();break;
case OPER_WAIT:do_wait();break;
case OPER_LEAVE:do_leave();break;
case OPER_FNSTCW:do_fnstcw();break;
case OPER_FLDCW:do_fldcw();break;
case OPER_FISTP:do_fistp();break;
case OPER_FCOMP:do_fcomp();break;
case OPER_FCOM:do_fcom();break;
case OPER_FIST:do_fist();break;
case OPER_FNSTSW:do_fnstsw();break;
case OPER_FSTSW:do_fstsw();break;
case OPER_FPTAN:do_fptan();break;
case OPER_FPATAN:do_fpatan();break;
case OPER_FSQRT:do_fsqrt();break;
case OPER_FLD1:do_fld1();break;
case OPER_FLDZ:do_fldz();break;
case OPER_FLDPI:do_fldpi();break;
case OPER_FLDL2E:do_fldl2e();break;
case OPER_FLDL2T:do_fldl2t();break;
case OPER_FLDLG2:do_fldlg2();break;
case OPER_FLDLN2:do_fldln2();break;
case OPER_FRNDINT:do_frndint();break;
case OPER_FSCALE:do_fscale();break;
case OPER_F2XM1:do_f2xm1();break;
case OPER_LAHF:do_lahf();break;
case OPER_SAHF:do_sahf();break;
case OPER_FYL2X:do_fyl2x();break;
case OPER_FXAM:do_fxam();break;
case OPER_FCLEX:do_fclex();break;
case OPER_JZ:do_jz();break;
case OPER_FPREM:do_fprem();break;
case OPER_JNZ:do_jnz();break;
case OPER_FSTCW:do_fstcw();break;
case OPER_FTST:do_ftst();break;
case OPER_FXTRACT:do_fxtract();break;
case OPER_REPE:do_repe();break;
default: this->runtime_error("error oper %d\n",oper);break;
}
return OK;
}
CReg * CVm::GetFPU(int index)
{
ASSERT(index >= 0 && index <= 7);
switch((this->fpu_top + index) % 8)
{
case 0: return this->GetReg(REG_ST0);break;
case 1: return this->GetReg(REG_ST1);break;
case 2: return this->GetReg(REG_ST2);break;
case 3: return this->GetReg(REG_ST3);break;
case 4: return this->GetReg(REG_ST4);break;
case 5: return this->GetReg(REG_ST5);break;
case 6: return this->GetReg(REG_ST6);break;
case 7: return this->GetReg(REG_ST7);break;
}
this->runtime_error("error index in GetFPU\n");
return NULL;
}