📄 vm_x86.c
字号:
int op;
int maxLength;
int v;
int i;
qboolean opt;
// allocate a very large temp buffer, we will shrink it later
maxLength = header->codeLength * 8;
buf = Z_Malloc( maxLength );
jused = Z_Malloc(header->instructionCount + 2 );
Com_Memset(jused, 0, header->instructionCount+2);
for(pass=0;pass<2;pass++) {
oc0 = -23423;
oc1 = -234354;
pop0 = -43435;
pop1 = -545455;
// translate all instructions
pc = 0;
instruction = 0;
code = (byte *)header + header->codeOffset;
compiledOfs = 0;
LastCommand = LAST_COMMAND_NONE;
while ( instruction < header->instructionCount ) {
if ( compiledOfs > maxLength - 16 ) {
Com_Error( ERR_FATAL, "VM_CompileX86: maxLength exceeded" );
}
vm->instructionPointers[ instruction ] = compiledOfs;
instruction++;
if ( pc > header->codeLength ) {
Com_Error( ERR_FATAL, "VM_CompileX86: pc > header->codeLength" );
}
op = code[ pc ];
pc++;
switch ( op ) {
case 0:
break;
case OP_BREAK:
EmitString( "CC" ); // int 3
break;
case OP_ENTER:
EmitString( "81 EE" ); // sub esi, 0x12345678
Emit4( Constant4() );
break;
case OP_CONST:
if (code[pc+4] == OP_LOAD4) {
EmitAddEDI4(vm);
EmitString( "BB" ); // mov ebx, 0x12345678
Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase);
EmitString( "8B 03" ); // mov eax, dword ptr [ebx]
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
pc++; // OP_LOAD4
instruction += 1;
break;
}
if (code[pc+4] == OP_LOAD2) {
EmitAddEDI4(vm);
EmitString( "BB" ); // mov ebx, 0x12345678
Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase);
EmitString( "0F B7 03" ); // movzx eax, word ptr [ebx]
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
pc++; // OP_LOAD4
instruction += 1;
break;
}
if (code[pc+4] == OP_LOAD1) {
EmitAddEDI4(vm);
EmitString( "BB" ); // mov ebx, 0x12345678
Emit4( (Constant4()&vm->dataMask) + (int)vm->dataBase);
EmitString( "0F B6 03" ); // movzx eax, byte ptr [ebx]
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
pc++; // OP_LOAD4
instruction += 1;
break;
}
if (code[pc+4] == OP_STORE4) {
opt = EmitMovEBXEDI(vm, (vm->dataMask & ~3));
EmitString( "B8" ); // mov eax, 0x12345678
Emit4( Constant4() );
// if (!opt) {
// EmitString( "81 E3" ); // and ebx, 0x12345678
// Emit4( vm->dataMask & ~3 );
// }
EmitString( "89 83" ); // mov dword ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
pc++; // OP_STORE4
instruction += 1;
break;
}
if (code[pc+4] == OP_STORE2) {
opt = EmitMovEBXEDI(vm, (vm->dataMask & ~1));
EmitString( "B8" ); // mov eax, 0x12345678
Emit4( Constant4() );
// if (!opt) {
// EmitString( "81 E3" ); // and ebx, 0x12345678
// Emit4( vm->dataMask & ~1 );
// }
EmitString( "66 89 83" ); // mov word ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
pc++; // OP_STORE4
instruction += 1;
break;
}
if (code[pc+4] == OP_STORE1) {
opt = EmitMovEBXEDI(vm, vm->dataMask);
EmitString( "B8" ); // mov eax, 0x12345678
Emit4( Constant4() );
// if (!opt) {
// EmitString( "81 E3" ); // and ebx, 0x12345678
// Emit4( vm->dataMask );
// }
EmitString( "88 83" ); // mov byte ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
pc++; // OP_STORE4
instruction += 1;
break;
}
if (code[pc+4] == OP_ADD) {
EmitString( "81 07" ); // add dword ptr [edi], 0x1234567
Emit4( Constant4() );
pc++; // OP_ADD
instruction += 1;
break;
}
if (code[pc+4] == OP_SUB) {
EmitString( "81 2F" ); // sub dword ptr [edi], 0x1234567
Emit4( Constant4() );
pc++; // OP_ADD
instruction += 1;
break;
}
EmitAddEDI4(vm);
EmitString( "C7 07" ); // mov dword ptr [edi], 0x12345678
lastConst = Constant4();
Emit4( lastConst );
if (code[pc] == OP_JUMP) {
jused[lastConst] = 1;
}
break;
case OP_LOCAL:
EmitAddEDI4(vm);
EmitString( "8D 86" ); // lea eax, [0x12345678 + esi]
oc0 = oc1;
oc1 = Constant4();
Emit4( oc1 );
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
break;
case OP_ARG:
EmitMovEAXEDI(vm); // mov eax,dword ptr [edi]
EmitString( "89 86" ); // mov dword ptr [esi+database],eax
// FIXME: range check
Emit4( Constant1() + (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
break;
case OP_CALL:
EmitString( "C7 86" ); // mov dword ptr [esi+database],0x12345678
Emit4( (int)vm->dataBase );
Emit4( pc );
EmitString( "FF 15" ); // call asmCallPtr
Emit4( (int)&asmCallPtr );
break;
case OP_PUSH:
EmitAddEDI4(vm);
break;
case OP_POP:
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
break;
case OP_LEAVE:
v = Constant4();
EmitString( "81 C6" ); // add esi, 0x12345678
Emit4( v );
EmitString( "C3" ); // ret
break;
case OP_LOAD4:
if (code[pc] == OP_CONST && code[pc+5] == OP_ADD && code[pc+6] == OP_STORE4) {
if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
compiledOfs -= 11;
vm->instructionPointers[ instruction-1 ] = compiledOfs;
}
pc++; // OP_CONST
v = Constant4();
EmitMovEBXEDI(vm, vm->dataMask);
if (v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
EmitString( "FF 83"); // inc dword ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
} else {
EmitString( "8B 83" ); // mov eax, dword ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
EmitString( "05" ); // add eax, const
Emit4( v );
if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
EmitString( "89 83" ); // mov dword ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
} else {
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
EmitString( "8B 1F" ); // mov ebx, dword ptr [edi]
EmitString( "89 83" ); // mov dword ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
}
}
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
pc++; // OP_ADD
pc++; // OP_STORE
instruction += 3;
break;
}
if (code[pc] == OP_CONST && code[pc+5] == OP_SUB && code[pc+6] == OP_STORE4) {
if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
compiledOfs -= 11;
vm->instructionPointers[ instruction-1 ] = compiledOfs;
}
EmitMovEBXEDI(vm, vm->dataMask);
EmitString( "8B 83" ); // mov eax, dword ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
pc++; // OP_CONST
v = Constant4();
if (v == 1 && oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
EmitString( "FF 8B"); // dec dword ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
} else {
EmitString( "2D" ); // sub eax, const
Emit4( v );
if (oc0 == oc1 && pop0 == OP_LOCAL && pop1 == OP_LOCAL) {
EmitString( "89 83" ); // mov dword ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
} else {
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
EmitString( "8B 1F" ); // mov ebx, dword ptr [edi]
EmitString( "89 83" ); // mov dword ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
}
}
EmitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4
pc++; // OP_SUB
pc++; // OP_STORE
instruction += 3;
break;
}
if (buf[compiledOfs-2] == 0x89 && buf[compiledOfs-1] == 0x07) {
compiledOfs -= 2;
vm->instructionPointers[ instruction-1 ] = compiledOfs;
EmitString( "8B 80"); // mov eax, dword ptr [eax + 0x1234567]
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
break;
}
EmitMovEBXEDI(vm, vm->dataMask);
EmitString( "8B 83" ); // mov eax, dword ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
break;
case OP_LOAD2:
EmitMovEBXEDI(vm, vm->dataMask);
EmitString( "0F B7 83" ); // movzx eax, word ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
break;
case OP_LOAD1:
EmitMovEBXEDI(vm, vm->dataMask);
EmitString( "0F B6 83" ); // movzx eax, byte ptr [ebx + 0x12345678]
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax
break;
case OP_STORE4:
EmitMovEAXEDI(vm);
EmitString( "8B 5F FC" ); // mov ebx, dword ptr [edi-4]
// if (pop1 != OP_CALL) {
// EmitString( "81 E3" ); // and ebx, 0x12345678
// Emit4( vm->dataMask & ~3 );
// }
EmitString( "89 83" ); // mov dword ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
break;
case OP_STORE2:
EmitMovEAXEDI(vm);
EmitString( "8B 5F FC" ); // mov ebx, dword ptr [edi-4]
// EmitString( "81 E3" ); // and ebx, 0x12345678
// Emit4( vm->dataMask & ~1 );
EmitString( "66 89 83" ); // mov word ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
break;
case OP_STORE1:
EmitMovEAXEDI(vm);
EmitString( "8B 5F FC" ); // mov ebx, dword ptr [edi-4]
// EmitString( "81 E3" ); // and ebx, 0x12345678
// Emit4( vm->dataMask );
EmitString( "88 83" ); // mov byte ptr [ebx+0x12345678], eax
Emit4( (int)vm->dataBase );
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
break;
case OP_EQ:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "75 06" ); // jne +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_NE:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "74 06" ); // je +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_LTI:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "7D 06" ); // jnl +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_LEI:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "7F 06" ); // jnle +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_GTI:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "7E 06" ); // jng +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_GEI:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "7C 06" ); // jnge +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_LTU:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "73 06" ); // jnb +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_LEU:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "77 06" ); // jnbe +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_GTU:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
EmitString( "76 06" ); // jna +6
EmitString( "FF 25" ); // jmp [0x12345678]
v = Constant4();
jused[v] = 1;
Emit4( (int)vm->instructionPointers + v*4 );
break;
case OP_GEU:
EmitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8
EmitString( "8B 47 04" ); // mov eax, dword ptr [edi+4]
EmitString( "3B 47 08" ); // cmp eax, dword ptr [edi+8]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -