aboutsummaryrefslogtreecommitdiff
path: root/unit-tests/intel_tests.cc
diff options
context:
space:
mode:
Diffstat (limited to 'unit-tests/intel_tests.cc')
-rw-r--r--unit-tests/intel_tests.cc4493
1 files changed, 4493 insertions, 0 deletions
diff --git a/unit-tests/intel_tests.cc b/unit-tests/intel_tests.cc
new file mode 100644
index 0000000..6ea3fb5
--- /dev/null
+++ b/unit-tests/intel_tests.cc
@@ -0,0 +1,4493 @@
+#include "../runtime/crypto.h"
+#include "../core/objects.h"
+#include "../core/osutils.h"
+#include "../core/streams.h"
+#include "../core/core.h"
+#include "../core/files.h"
+#include "../core/processors.h"
+#include "../core/pefile.h"
+#include "../core/intel.h"
+
+#include "testfileintel.h"
+
+TEST(IntelTest, x86_AsmMarkers)
+{
+ uint8_t buf[] = {
+ 0x55, // 004B58EC push ebp
+ 0x8B, 0xEC, // 004B58ED mov ebp, esp
+ 0x6A, 0x00, // 004B58EF push 00
+ 0x6A, 0x00, // 004B58F1 push 00
+ 0x6A, 0x00, // 004B58F3 push 00
+ 0x53, // 004B58F5 push ebx
+ 0x8B, 0xD8, // 004B58F6 mov ebx, eax
+ 0x33, 0xC0, // 004B58F8 xor eax, eax
+ 0x55, // 004B58FA push ebp
+ 0x68, 0xDA, 0x59, 0x4B, 0x00, // 004B58FB push 004B59DA
+ 0x64, 0xFF, 0x30, // 004B5900 push dword ptr fs:[eax]
+ 0x64, 0x89, 0x20, // 004B5903 mov fs:[eax], esp
+ 0xEB, 0x10, // 004B5906 jmp 004B5918
+ 0x56, 0x4D, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x00, // db 'VMProtect begin', 0
+ 0x8D, 0x55, 0xFC, // 004B5918 lea edx, [ebp-04]
+ 0x8B, 0x83,
+ 0x8C, 0x03, 0x00, 0x00, // 004B591A mov eax, [ebx+0000038C]
+ 0xE8, 0x0A, 0xE0, 0xFC, 0xFF, // 004B5920 call 00483930
+ 0x8B, 0x45, 0xFC, // 004B5925 mov eax, [ebp-04]
+ 0x33, 0xD2, // 004B5928 xor edx, edx
+ 0xE8, 0xD4, 0xCB, 0xF5, 0xFF, // 004B592A call 00412504
+ 0xB9, 0x11, 0x00, 0x00, 0x00, // 004B592F mov ecx, 00000011
+ 0x99, // 004B5930 cdq
+ 0xF7, 0xF9, // 004B5931 idiv ecx
+ 0x83, 0xFA, 0x0D, // 004B5933 cmp edx, 0D
+ 0x75, 0x2F, // 004B5936 jnz 004B596C
+ 0x68, 0xE8, 0x59, 0x4B, 0x00, // 004B5938 push 004B59E8
+ 0xE8, 0x81, 0xFC, 0xFF, 0xFF, // 004B593D call 004B55C8
+ 0x8B, 0xD0, // 004B5942 mov edx, eax
+ 0x8D, 0x45, 0xF8, // 004B5944 lea eax, [ebp-08]
+ 0xE8, 0x6F, 0x10, 0xF5, 0xFF, // 004B5947 call 004069C0
+ 0x8B, 0x45, 0xF8, // 004B594C mov eax, [ebp-08]
+ 0x6A, 0x00, // 004B594F push 00
+ 0x6A, 0xFF, // 004B5951 push -01
+ 0x6A, 0xFF, // 004B5953 push -01
+ 0x6A, 0x00, // 004B5955 push 00
+ 0x0F, 0xB7, 0x0D,
+ 0xFC, 0x59, 0x4B, 0x00, // 004B5957 movzx ecx, word ptr [004B59FC]
+ 0xB2, 0x02, // 004B595E mov dl, 02
+ 0xE8, 0xAA, 0x4A, 0xFB, 0xFF, // 004B5960 call 0046A414
+ 0xEB, 0x4B, // 004B5965 jmp 004B59B7
+ 0x68, 0x00, 0x5A, 0x4B, 0x00, // 004B5967 push 004B5A00
+ 0xE8, 0x52, 0xFC, 0xFF, 0xFF, // 004B596C call 004B55C8
+ 0x8B, 0xD0, // 004B5971 mov edx, eax
+ 0x8D, 0x45, 0xF4, // 004B5973 lea eax, [ebp-0C]
+ 0xE8, 0x40, 0x10, 0xF5, 0xFF, // 004B5976 call 004069C0
+ 0x8B, 0x45, 0xF4, // 004B597B mov eax, [ebp-0C]
+ 0x6A, 0x00, // 004B597E push 00
+ 0x6A, 0xFF, // 004B5980 push -01
+ 0x6A, 0xFF, // 004B5982 push -01
+ 0x6A, 0x00, // 004B5984 push 00
+ 0x0F, 0xB7, 0x0D,
+ 0xFC, 0x59, 0x4B, 0x00, // 004B5986 movzx ecx, word ptr [004B59FC]
+ 0xB2, 0x01, // 004B598D mov dl, 01
+ 0xE8, 0x7B, 0x4A, 0xFB, 0xFF, // 004B598F call 0046A414
+ 0x8B, 0x83,
+ 0x8C, 0x03, 0x00, 0x00, // 004B5994 mov eax, [ebx+0000038C]
+ 0x8B, 0x10, // 004B599A mov edx, [eax]
+ 0xFF, 0x92,
+ 0xE8, 0x00, 0x00, 0x00, // 004B599C call dword ptr [edx+000000E8]
+ 0xEB, 0x0E, // 004B59A2 jmp 004B59B7
+ 0x56, 0x4D, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x20, 0x65, 0x6E, 0x64, 0x00, // db 'VMProtect end', 00
+ 0x33, 0xC0, // 004B59B2 xor eax, eax
+ 0x5A, // 004B59B4 pop edx
+ 0x59, // 004B59B5 pop ecx
+ 0x59, // 004B59B6 pop ecx
+ 0x64, 0x89, 0x10, // 004B59B7 mov fs:[eax], edx
+ 0x68, 0xE1, 0x59, 0x4B, 0x00, // 004B59BA push 004B59E1
+ 0x8D, 0x45, 0xF4, // 004B59BF lea eax, [ebp-0C]
+ 0xBA, 0x02, 0x00, 0x00, 0x00, // 004B59C2 mov edx, 00000002
+ 0xE8, 0x6B, 0x0E, 0xF5, 0xFF, // 004B59C7 call 0040683C
+ 0x8D, 0x45, 0xFC, // 004B59CC lea eax, [ebp-04]
+ 0xE8, 0x5B, 0x0E, 0xF5, 0xFF, // 004B59CF call 00406834
+ 0xC3, // 004B59D4 ret
+ 0xE9, 0xC1, 0xFD, 0xF4, 0xFF, // 004B59D5 jmp 004057A0
+ 0xEB, 0xE3, // 004B59DA jmp 004B59C4
+ 0x5B, // 004B59DC pop ebx
+ 0x8B, 0xE5, // 004B59DD mov esp, ebp
+ 0x5D, // 004B59DF pop ebp
+ 0xC3, // 004B59E0 ret
+ 0x90, 0x90, 0x90, 0x90
+ };
+
+ IntelFunction *func;
+ MapFunctionList *map_function_list;
+ MapFunction *map_function;
+ IntelCommand *command;
+
+ TestFile test_file(osDWord);
+ TestArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x004B58EC, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 73ul);
+ map_function_list = arch.map_function_list();
+ map_function = map_function_list->GetFunctionByName("VMProtectMarker1");
+ ASSERT_TRUE(map_function != NULL);
+ EXPECT_EQ(map_function->address(), 0x004B5906ull);
+ EXPECT_EQ(func->ReadFromFile(arch, map_function->address()), 45ul);
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+}
+
+TEST(IntelTest, CompilerFunction_Delphi)
+{
+ PEFile pf(NULL);
+
+ EXPECT_EQ(pf.Open("test-binaries/win32-app-delphi-i386", foRead), osSuccess);
+ EXPECT_EQ(pf.count(), 1ul);
+ PEArchitecture &arch = *pf.arch_pe();
+ IntelFunction command_list;
+ EXPECT_EQ(command_list.ReadFromFile(arch, 0x004BBC48), 17ul);
+ EXPECT_EQ(command_list.ReadFromFile(arch, 0x004B5A34), 2ul);
+}
+
+uint8_t char2hex(char d)
+{
+ if ((d >= '0') && (d <= '9')) {
+ return (d - '0');
+ }
+ if ((d >= 'A') && (d <= 'F')) {
+ return (d - '7');
+ }
+ if ((d >= 'a') && (d <= 'f')) {
+ return (d - 'W');
+ }
+ return 0;
+}
+
+void ascii2hex(const char *inp, uint8_t *out, size_t size)
+{
+ size_t i, j;
+
+ for (i=0, j=0; j<size/2; j++, i+=2) {
+ out[j] = (char2hex(inp[i]) << 4) + char2hex(inp[i+1]);
+ }
+}
+
+TEST(IntelTest, x86)
+{
+// TestFile test_file(osDWord);
+ TestFile test_file(osQWord);
+ IArchitecture &arch = *test_file.item(0);
+
+ IntelCommand intel_command(NULL, arch.cpu_address_size(), 0x401000);
+ size_t i, k, n;
+ FileStream fs;
+ bool status;
+ std::string line, udisstr, intel_str;
+ uint8_t dump[40], sse_preffix;
+
+ return;
+
+ status = fs.Open("test-binaries/intel-x64-opcodes.txt", fmOpenRead | fmShareDenyNone); //-V779
+
+ ASSERT_TRUE(status);
+ for (;;) {
+ if (!fs.ReadLine(line))
+ break;
+ i = line.find(' ');
+ if (i > 0) {
+ ascii2hex(line.c_str(), dump, i);
+
+ n = 0;
+ sse_preffix = 0;
+ for (k = 0; k < i/2; k++) {
+ if (dump[k] == 0xF2 || dump[k] == 0xF3 || (dump[k] == 0x66 && sse_preffix == 0))
+ sse_preffix = dump[k];
+ if (dump[k] == 0x26 ||
+ dump[k] == 0x2e ||
+ dump[k] == 0x36 ||
+ dump[k] == 0x3e ||
+ dump[k] == 0x64 ||
+ dump[k] == 0x65 ||
+ dump[k] == 0x66 ||
+ dump[k] == 0x67 ||
+ dump[k] == 0xF2 ||
+ dump[k] == 0xF3
+ ) {
+ n++;
+ } else {
+ break;
+ }
+ }
+
+ // VMRUN is not decoded by udis when ud_set_vendor(&u, UD_VENDOR_INTEL) is called; not a bug
+ if (dump[n] == 0x0f && dump[n+1] == 0x01 && dump[n+2] >= 0xc0)
+ continue;
+
+ // Workarounds for UDIS bugs (low priority of fixing)
+ // UDIS workaround: mov invalid_CR, reg, mov reg, invalid_CR
+ if (dump[n] == 0x0f && (dump[n+1] == 0x20 || dump[n + 1] == 0x22)) {
+ unsigned cr = (dump[n+2] & 0x38) >> 3;
+ if (cr == 1 || (cr >= 5 && cr <= 7) || cr >= 9)
+ continue;
+ }
+
+ if (arch.cpu_address_size() == osQWord) {
+ if ((dump[n] >= 0x48 && dump[n] <= 0x4f && dump[n+1] == 0x6d)
+ || (dump[n] == 0x48 && dump[n+1] == 0x6f)
+ || (dump[n] == 0x9c)
+ || (dump[n] == 0x9d)
+ )
+ continue;
+ }
+
+ //dprint((line.c_str()));
+ //dprint(("\n"));
+
+ test_file.OpenFromMemory(dump, (uint32_t)(i / 2));
+ udisstr = line.substr(i + 1);
+ try {
+ if (intel_command.ReadFromFile(arch) != i / 2) {
+ if (intel_command.type() == cmDB && (line.substr(i + 1, 2).compare("db") == 0 || udisstr.find("invalid") != udisstr.npos))
+ continue;
+
+ FAIL() << "Cannot disassemble:\nudis: '" << udisstr
+ << "'\nintel_command: '" << intel_command.text() << "'\n" <<
+ "binary: " << line.substr(0, i);
+ }
+ } catch (std::runtime_error & e) {
+ FAIL() << "Exception '" << e.what() << "'\n" << "Input: " << line;
+ }
+ intel_str = intel_command.text();
+ std::transform(intel_str.begin(), intel_str.end(), intel_str.begin(), ::tolower);
+ if (intel_str.compare(udisstr) != 0) {
+ if (udisstr.find("invalid") != udisstr.npos && intel_command.type() == cmDB)
+ continue;
+
+ if (udisstr.find("rip+") != udisstr.npos) {
+ //dprint((line.c_str()));
+ //dprint(("\n"));
+ continue;
+ }
+
+ if (intel_command.type() == cmLoop ||
+ intel_command.type() == cmLoope ||
+ intel_command.type() == cmLoopne ||
+ intel_command.type() == cmJCXZ ||
+ intel_command.type() == cmJmp ||
+ intel_command.type() == cmCall ||
+ intel_command.type() == cmPusha ||
+ intel_command.type() == cmPopa ||
+ intel_command.type() == cmJmpWithFlag)
+ continue;
+ FAIL() << "Disasm error:\nudis: '" << udisstr
+ << "'\nintel_command: '" << intel_str << "'\n" <<
+ "binary: " << line.substr(0, i);
+ }
+ }
+ }
+};
+
+TEST(IntelTest, x86_Disasm)
+{
+ PEFile pf(NULL);
+ IntelFunction command_list;
+
+ EXPECT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
+ EXPECT_EQ(pf.count(), 1ul);
+ IArchitecture &arch = *pf.item(0);
+ EXPECT_EQ(command_list.ReadFromFile(arch, 0x00401198), 53ul);
+ EXPECT_TRUE(command_list.GetCommandByNearAddress(0x00401235) != NULL);
+ EXPECT_EQ(command_list.item(0)->address(), 0x00401198ull);
+ EXPECT_EQ(command_list.item(command_list.count() - 1)->next_address(), 0x00401240ull);
+}
+
+TEST(IntelTest, x86_DelphiSEH)
+{
+ uint8_t buf[] = {
+ 0x55, // push ebp
+ 0x8B, 0xEC, // mov ebp, esp
+ 0x83, 0xC4, 0xEC, // add esp, -14
+ 0x53, // push ebx
+ 0x56, // push esi
+ 0x57, // push edi
+ 0x33, 0xC0, // xor eax, eax
+ 0x89, 0x45, 0xEC, // mov [ebp-14], eax
+ 0xA1, 0x9C, 0x1D, 0x41, 0x00, // mov eax, [00411D9C]
+ 0xC6, 0x00, 0x01, // mov byte ptr [eax], 01
+ 0xB8, 0xB4, 0xE4, 0x40, 0x00, // mov eax, 0040E4B4
+ 0xE8, 0x10, 0x89, 0xFF, 0xFF, // call 00408AA0
+ 0x33, 0xC0, // xor eax, eax
+ 0x55, // push ebp
+ 0x68, 0x37, 0x02, 0x41, 0x00, // push 00410237
+ 0x64, 0xFF, 0x30, // push dword ptr fs:[eax]
+ 0x64, 0x89, 0x20, // mov fs:[eax], esp
+ 0x33, 0xC0, // xor eax, eax
+ 0x55, // push ebp
+ 0x68, 0xD6, 0x01, 0x41, 0x00, // push 004101D6
+ 0x64, 0xFF, 0x30, // push dword ptr fs:[eax]
+ 0x64, 0x89, 0x20, // mov fs:[eax], esp
+ 0xB8, 0x32, 0x00, 0x00, 0x00, // mov eax, 00000032
+ 0xE8, 0x06, 0x3B, 0xFF, 0xFF, // call 00403CBC
+ 0x8B, 0xD0, // mov edx, eax
+ 0xA1, 0xE0, 0x1C, 0x41, 0x00, // mov eax, [00411CE0]
+ 0xE8, 0x72, 0x42, 0xFF, 0xFF, // call 00404434
+ 0xE8, 0x99, 0x42, 0xFF, 0xFF, // call 00404460
+ 0xE8, 0xA0, 0x39, 0xFF, 0xFF, // call 00403B6C
+ 0x33, 0xC0, // xor eax, eax
+ 0x5A, // pop edx
+ 0x59, // pop ecx
+ 0x59, // pop ecx
+ 0x64, 0x89, 0x10, // mov fs:[eax], edx
+ 0xEB, 0x4B, // jmp 00410221
+ 0xE9, 0x21, 0x4F, 0xFF, 0xFF, // jmp 004050FC
+ 0x01, 0x00, 0x00, 0x00, // dd 00000001
+ 0x54, 0x90, 0x41, 0x00, // dd 00419054
+ 0xE7, 0x01, 0x41, 0x00, // dd 004101E7
+ 0x8B, 0xD8, // mov ebx, eax
+ 0x8D, 0x55, 0xEC, // lea edx, [ebp-14]
+ 0x8B, 0x03, // mov eax, [ebx]
+ 0xE8, 0xBD, 0x45, 0xFF, 0xFF, // call 004047B0
+ 0x8B, 0x55, 0xEC, // mov edx, [ebp-14]
+ 0xA1, 0xE0, 0x1C, 0x41, 0x00, // mov eax, [00411CE0]
+ 0xE8, 0x8C, 0x64, 0xFF, 0xFF, // call 0040668C
+ 0xBA, 0x54, 0x02, 0x41, 0x00, // mov edx, 00410254
+ 0xE8, 0x82, 0x64, 0xFF, 0xFF, // call 0040668C
+ 0x8B, 0x53, 0x04, // mov edx, [ebx+04]
+ 0xE8, 0x7A, 0x64, 0xFF, 0xFF, // call 0040668C
+ 0xE8, 0x49, 0x42, 0xFF, 0xFF, // call 00404460
+ 0xE8, 0x50, 0x39, 0xFF, 0xFF, // call 00403B6C
+ 0xE8, 0x07, 0x52, 0xFF, 0xFF, // call 00405428
+ 0x33, 0xC0, // xor eax, eax
+ 0x5A, // pop edx
+ 0x59, // pop ecx
+ 0x59, // pop ecx
+ 0x64, 0x89, 0x10, // mov fs:[eax], edx
+ 0x68, 0x3E, 0x02, 0x41, 0x00, // push 0041023E
+ 0x8D, 0x45, 0xEC, // lea eax, [ebp-14]
+ 0xE8, 0x66, 0x5E, 0xFF, 0xFF, // call 0040609C
+ 0xC3, // ret
+ 0xE9, 0x48, 0x50, 0xFF, 0xFF, // jmp 00405284
+ 0xEB, 0xF0, // jmp 0041022E
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0xE8, 0xF6, 0x56, 0xFF, 0xFF, // call 0040593C
+ 0xC3 // ret
+ };
+
+ ICommand *command;
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00410170, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ EXPECT_EQ(func->count(), 69ul);
+ command = func->GetCommandByAddress(0x004101a1);
+ EXPECT_EQ(command->link()->type(), ltFilterSEHBlock);
+ command = func->GetCommandByAddress(0x004101DB);
+ EXPECT_EQ(command->text(), "dd 00000001");
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 00419054");
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 004101E7");
+ EXPECT_EQ(command->link()->type(), ltMemSEHBlock);
+ command = func->GetCommandByAddress(0x00410229);
+ EXPECT_EQ(command->link()->type(), ltFinallyBlock);
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+ // Check the compilation prepare
+ MemoryManager manager(&arch);
+ CompileContext ctx;
+ ctx.file = &arch;
+ ctx.manager = &manager;
+ ASSERT_TRUE(func->Prepare(ctx));
+ ASSERT_TRUE(func->PrepareExtCommands(ctx));
+ ASSERT_EQ(manager.count(), 2ul);
+ MemoryRegion *region = manager.item(0);
+ EXPECT_EQ(region->address(), 0x00410175ull);
+ EXPECT_EQ(region->size(), 0x66ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+ region = manager.item(1);
+ EXPECT_EQ(region->address(), 0x004101e7ull);
+ EXPECT_EQ(region->size(), 0x60ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+}
+
+TEST(IntelTest, x86_ParseSDK)
+{
+ PEFile pf(NULL);
+ IntelFunction *func;
+ MapFunctionList *map_function_list;
+ MapFunction *map_function;
+ IntelCommand *command;
+
+ EXPECT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
+ EXPECT_EQ(pf.count(), 1ul);
+ IArchitecture &arch = *pf.item(0);
+ map_function_list = arch.map_function_list();
+ map_function = map_function_list->GetFunctionByAddress(0x004011A3);
+ EXPECT_EQ(map_function->name().compare("VMProtectMarker \"Test marker\""), 0);
+ map_function = map_function_list->GetFunctionByAddress(0x00403049);
+ EXPECT_EQ(map_function->name().compare("string \"Correct password\""), 0);
+ map_function = map_function_list->GetFunctionByAddress(0x00403066);
+ EXPECT_EQ(map_function->name().compare("string \"Incorrect password\""), 0);
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(0x004011A3, ctVirtualization, 0, true, NULL));
+ EXPECT_EQ(func->count(), 47ul);
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+}
+
+TEST(IntelTest, Clone)
+{
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
+ EXPECT_EQ(pf.count(), 1ul);
+ IFunctionList *function_list = pf.item(0)->function_list();
+ Folder *f1 = pf.folder_list()->Add("Folder1");
+ Folder *f2 = f1->Add("Folder2");
+ IFunction *func = function_list->AddByAddress(0x004011A3, ctUltra, 0, false, f2);
+ size_t command_count = func->count();
+ size_t link_count = func->link_list()->count();
+ uint64_t link_address = func->link_list()->item(2)->from_command()->address();
+ IFunctionList *clone_function_list = function_list->Clone(NULL);
+ pf.Close();
+ // Check clone function list.
+ //EXPECT_EQ(clone_function_list->root_folder()->count(), 1);
+ //EXPECT_EQ(clone_function_list->root_folder()->item(0)->count(), 1);
+ //EXPECT_EQ(clone_function_list->root_folder()->item(0)->name().compare("Folder1"), 0);
+
+ ASSERT_EQ(clone_function_list->count(), 1ul);
+ func = clone_function_list->item(0);
+ EXPECT_EQ(func->compilation_type(), ctUltra);
+ EXPECT_EQ(func->need_compile(), false);
+ //EXPECT_EQ(func->folder()->name().compare("Folder2"), 0);
+ ASSERT_EQ(func->count(), command_count);
+ ASSERT_EQ(func->link_list()->count(), link_count);
+ EXPECT_EQ(func->link_list()->item(2)->from_command()->address(), link_address);
+ delete clone_function_list;
+}
+
+TEST(IntelTest, x86_Switch)
+{
+ uint8_t buf[] = {
+ 0x83, 0xEC, 0x0C, // sub esp, 0C
+ 0x53, // push ebx
+ 0x56, // push esi
+ 0x57, // push edi
+ 0x89, 0x65, 0xE8, // mov [ebp-18], esp
+ 0x8B, 0xF1, // mov esi, ecx
+ 0x33, 0xC0, // xor eax, eax
+ 0x89, 0x45, 0xE4, // mov [ebp-1C], eax
+ 0x89, 0x45, 0xFC, // mov [ebp-04], eax
+ 0x52, // push edx
+ 0x51, // push ecx
+ 0x53, // push ebx
+ 0xB8, 0x68, 0x58, 0x4D, 0x56, // mov eax, 564D5868
+ 0x33, 0xDB, // xor ebx, ebx
+ 0xB9, 0x0A, 0x00, 0x00, 0x00, // mov ecx, 0000000A
+ 0xBA, 0x58, 0x56, 0x00, 0x00, // mov edx, 00005658
+ 0xED, // in eax, dx
+ 0x81, 0xFB, 0x68, 0x58, 0x4D, 0x56, // cmp ebx, 564D5868
+ 0x75, 0x03, // jnz 00403050
+ 0x89, 0x4D, 0xE4, // mov [ebp-1C], ecx
+ 0x5B, // pop ebx
+ 0x59, // pop ecx
+ 0x5A, // pop edx
+ 0x8B, 0x45, 0xE4, // mov eax, [ebp-1C]
+ 0x48, // dec eax
+ 0x83, 0xF8, 0x03, // cmp eax, 03
+ 0x0F, 0x87, 0x97, 0x00, 0x00, 0x00, // jnbe 004030F7
+ 0xFF, 0x24, 0x85, 0x40, 0x31, 0x40, 0x00, // jmp dword ptr [eax*4+00403140]
+ 0x68, 0x74, 0xD8, 0x4E, 0x00, // push 004ED874
+ 0xE8, 0xDF, 0x00, 0x00, 0x00, // call 00403150
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB0, 0x01, // mov al, 01
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0x68, 0x94, 0xD8, 0x4E, 0x00, // push 004ED894
+ 0xE8, 0xBB, 0x00, 0x00, 0x00, // call 00403150
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB0, 0x01, // mov al, 01
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0x68, 0xB8, 0xD8, 0x4E, 0x00, // push 004ED8B8
+ 0xE8, 0x97, 0x00, 0x00, 0x00, // call 00403150
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB0, 0x01, // mov al, 01
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0x68, 0xDC, 0xD8, 0x4E, 0x00, // push 004ED8DC
+ 0xE8, 0x73, 0x00, 0x00, 0x00, // call 00403150
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB0, 0x01, // mov al, 01
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0x68, 0x04, 0xD9, 0x4E, 0x00, // push 004ED904
+ 0xE8, 0x4F, 0x00, 0x00, 0x00, // call 00403150
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB0, 0x01, // mov al, 01
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 00000001
+ 0xC3, // ret
+ 0x8B, 0x65, 0xE8, // mov esp, [ebp-18]
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0x32, 0xC0, // xor al, al
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0xCD, 0xCD, // alignment
+ 0x67, 0x30, 0x40, 0x00, // dd 00403067
+ 0x8B, 0x30, 0x40, 0x00, // dd 0040308B
+ 0xAF, 0x30, 0x40, 0x00, // dd 004030AF
+ 0xD3, 0x30, 0x40, 0x00, // dd 004030D3
+ 0x00, 0x00, 0x00, 0x00 // dd 0
+ };
+
+ ICommand *command;
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x0040301D, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 92ul);
+ command = func->GetCommandByAddress(0x00403140);
+ EXPECT_EQ(command->text(), "dd 00403067");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 0040308B");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 004030AF");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 004030D3");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+ // Check the compilation prepare
+ MemoryManager manager(&arch);
+ CompileContext ctx;
+ ctx.file = &arch;
+ ctx.manager = &manager;
+ ASSERT_TRUE(func->Prepare(ctx));
+ ASSERT_TRUE(func->PrepareExtCommands(ctx));
+ ASSERT_EQ(manager.count(), 2ul);
+ MemoryRegion *region = manager.item(0);
+ EXPECT_EQ(region->address(), 0x00403022ull);
+ EXPECT_EQ(region->size(), 0xF9ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+ region = manager.item(1);
+ EXPECT_EQ(region->address(), 0x00403140ull);
+ EXPECT_EQ(region->size(), 0x10ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+}
+
+TEST(IntelTest, x86_MsvcSEH)
+{
+ uint8_t buf[] = {
+ 0x55, // push ebp
+ 0x8B, 0xEC, // mov ebp, esp
+ 0x6A, 0xFF, // push -01
+ 0x68, 0x48, 0x32, 0x40, 0x00, // push 00403248
+ 0x68, 0xE4, 0x7A, 0x4D, 0x00, // push 004D7AE4
+ 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, // mov eax, fs:[00000000]
+ 0x50, // push eax
+ 0x64, 0x89, 0x25, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], esp
+ 0x83, 0xEC, 0x08, // sub esp, 08
+ 0x53, // push ebx
+ 0x56, // push esi
+ 0x57, // push edi
+ 0x89, 0x65, 0xE8, // mov [ebp-18], esp
+ 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, // mov dword ptr [ebp-04], 00000000
+ 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 00000001
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop
+ 0x68, 0x14, 0xD9, 0x4E, 0x00, // push 004ED914
+ 0x8B, 0xF1, // mov esi, ecx
+ 0xE8, 0x47, 0xFF, 0xFF, 0xFF, // call 00403150
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB0, 0x01, // mov al, 01
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 00000001
+ 0xC3, // ret
+ 0x8B, 0x65, 0xE8, // mov esp, [ebp-18]
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0x32, 0xC0, // xor al, al
+ 0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0xCD, 0xCD, // alignment
+ 0xFF, 0xFF, 0xFF, 0xFF, // dd FFFFFFFF
+ 0x23, 0x32, 0x40, 0x00, // dd 00403223
+ 0x29, 0x32, 0x40, 0x00, // dd 00403229
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00 // dd 0
+ };
+
+ ICommand *command;
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x004031C0, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 55ul);
+ command = func->GetCommandByAddress(0x00403248);
+ EXPECT_EQ(command->text(), "dd FFFFFFFF");
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 00403223");
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 00403229");
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+ // Check the compilation prepare
+ MemoryManager manager(&arch);
+ CompileContext ctx;
+ ctx.file = &arch;
+ ctx.manager = &manager;
+ ASSERT_TRUE(func->Prepare(ctx));
+ ASSERT_TRUE(func->PrepareExtCommands(ctx));
+ ASSERT_EQ(manager.count(), 1ul);
+ MemoryRegion *region = manager.item(0);
+ EXPECT_EQ(region->address(), 0x004031C5ull);
+ EXPECT_EQ(region->size(), 0x81ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+}
+
+TEST(IntelTest, x64_Switch)
+{
+ uint8_t buf[] = {
+ 0x83, 0xFB, 0x06, // cmp ebx, 06
+ 0x74, 0x0A, // jz 000000010001874A
+ 0x83, 0xFB, 0x07, // cmp ebx, 07
+ 0x74, 0x05, // jz 000000010001874A
+ 0x83, 0xFB, 0x08, // cmp ebx, 08
+ 0x75, 0x35, // jnz 000000010001877F
+ 0xBA, 0x04, 0xE8, 0x00, 0x00, // mov edx, 0000E804
+ 0xE8, 0xBA, 0x2B, 0x01, 0x00, // call 000000010002B30E
+ 0x48, 0x85, 0xC0, // test rax, rax
+ 0x74, 0x0A, // jz 0000000100018763
+ 0x33, 0xD2, // xor edx, edx
+ 0x48, 0x8B, 0xC8, // mov rcx, rax
+ 0xE8, 0x17, 0x20, 0x01, 0x00, // call 000000010002A77A
+ 0xBA, 0x05, 0xE8, 0x00, 0x00, // mov edx, 0000E805
+ 0x48, 0x8B, 0xCF, // mov rcx, rdi
+ 0xE8, 0x9E, 0x2B, 0x01, 0x00, // call 000000010002B30E
+ 0x48, 0x85, 0xC0, // test rax, rax
+ 0x74, 0x0A, // jz 000000010001877F
+ 0x33, 0xD2, // xor edx, edx
+ 0x48, 0x8B, 0xC8, // mov rcx, rax
+ 0xE8, 0xFB, 0x1F, 0x01, 0x00, // call 000000010002A77A
+ 0x8D, 0x43, 0xFF, // lea eax, [rbx-01]
+ 0x83, 0xF8, 0x09, // cmp eax, 09
+ 0x77, 0x27, // jnbe 00000001000187AE
+ 0x48, 0x8D, 0x15, 0x72, 0x78, 0xFE, 0xFF, // lea rdx, [0000000100000000]
+ 0x48, 0x98, // cdqe
+ 0x8B, 0x8C, 0x82, 0xF8, 0x87, 0x01, 0x00, // mov ecx, [rdx+rax*4+00000000000187F8]
+ 0x48, 0x03, 0xCA, // add rcx, rdx
+ 0xFF, 0xE1, // jmp rcx
+ 0x4C, 0x8B, 0x8F, 0x58, 0x01, 0x00, 0x00, // mov r9, [rdi+0000000000000158]
+ 0xEB, 0x10, // jmp 00000001000187B5
+ 0x4C, 0x8B, 0x8F, 0x60, 0x01, 0x00, 0x00, // mov r9, [rdi+0000000000000160]
+ 0xEB, 0x07, // jmp 00000001000187B5
+ 0x4C, 0x8B, 0x8F, 0x50, 0x01, 0x00, 0x00, // mov r9, [rdi+0000000000000150]
+ 0x48, 0x8B, 0x4F, 0x40, // mov rcx, [rdi+40]
+ 0xBA, 0x80, 0x00, 0x00, 0x00, // mov edx, 00000080
+ 0x44, 0x8D, 0x42, 0x81, // lea r8d, [rdx-7F]
+ 0xFF, 0x15, 0xA8, 0xA2, 0xFE, 0xFF, // call qword ptr [0000000100002A70]
+ 0x48, 0x8D, 0x0D, 0x81, 0x77, 0x02, 0x00, // lea rcx, [000000010003FF50]
+ 0x41, 0xB8, 0x01, 0x00, 0x00, 0x00, // mov r8d, 00000001
+ 0x8B, 0xD3, // mov edx, ebx
+ 0xE8, 0xD4, 0x77, 0x00, 0x00, // call 000000010001FFB0
+ 0x48, 0x8B, 0xCF, // mov rcx, rdi
+ 0x48, 0x8B, 0xD0, // mov rdx, rax
+ 0xE8, 0x87, 0x28, 0x01, 0x00, // call 000000010002B06E
+ 0x48, 0x8B, 0x7C, 0x24, 0x48, // mov rdi, [rsp+48]
+ 0x48, 0x8B, 0x5C, 0x24, 0x40, // mov rbx, [rsp+40]
+ 0x33, 0xC0, // xor eax, eax
+ 0x48, 0x83, 0xC4, 0x28, // add rsp, 28
+ 0xC3, // ret
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0xA5, 0x87, 0x01, 0x00, // dd 000187A5
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0x9C, 0x87, 0x01, 0x00, // dd 0001879C
+ 0x9C, 0x87, 0x01, 0x00, // dd 0001879C
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0xAE, 0x87, 0x01, 0x00, // dd 000187AE
+ 0x00, 0x00, 0x00, 0x00 // dd 0
+ };
+
+ ICommand *command;
+ IntelFunction *func;
+ TestFile test_file(osQWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x010001873Bull, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ EXPECT_EQ(func->count(), 60ul);
+ command = func->GetCommandByAddress(0x01000187F8ull);
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187A5");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 0001879C");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 0001879C");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ command = func->GetCommandByAddress(command->next_address());
+ EXPECT_EQ(command->text(), "dd 000187AE");
+ EXPECT_EQ(command->link()->type(), ltCase);
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+ // Check the compilation prepare
+ MemoryManager manager(&arch);
+ CompileContext ctx;
+ ctx.file = &arch;
+ ctx.manager = &manager;
+ ASSERT_TRUE(func->Prepare(ctx));
+ ASSERT_TRUE(func->PrepareExtCommands(ctx));
+ ASSERT_EQ(manager.count(), 1ul);
+ MemoryRegion *region = manager.item(0);
+ EXPECT_EQ(region->address(), 0x0100018740ull);
+ EXPECT_EQ(region->size(), 0xe0ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+}
+
+TEST(IntelTest, x86_MsvcSEH2)
+{
+ uint8_t buf[] = {
+ 0x55, // push ebp
+ 0x8B, 0xEC, // mov ebp, esp
+ 0x6A, 0xFF, // push -01
+ 0x68, 0x7E, 0x10, 0x40, 0x00, // push 0040107E
+ 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, // mov eax, fs:[00000000]
+ 0x50, // push eax
+ 0x51, // push ecx
+ 0x53, // push ebx
+ 0x56, // push esi
+ 0x57, // push edi
+ 0xA1, 0x00, 0x30, 0x40, 0x00, // mov eax, [00403000]
+ 0x33, 0xC5, // xor eax, ebp
+ 0x50, // push eax
+ 0x8D, 0x45, 0xF4, // lea eax, [ebp-0C]
+ 0x64, 0xA3, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], eax
+ 0x89, 0x65, 0xF0, // mov [ebp-10], esp
+ 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, // mov dword ptr [ebp-04], 00000000
+ 0x8B, 0x45, 0x08, // mov eax, [ebp+08]
+ 0x99, // cdq
+ 0x33, 0xC9, // xor ecx, ecx
+ 0xF7, 0xF9, // idiv ecx
+ 0x85, 0xC0, // test eax, eax
+ 0x75, 0x0E, // jnz 0040104A
+ 0x68, 0xF4, 0x20, 0x40, 0x00, // push 004020F4
+ 0xFF, 0x15, 0xA0, 0x20, 0x40, 0x00, // call dword ptr [004020A0]
+ 0x83, 0xC4, 0x04, // add esp, 04
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0x8B, 0x4D, 0xF4, // mov ecx, [ebp-0C]
+ 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
+ 0x59, // pop ecx
+ 0x5F, // pop edi
+ 0x5E, // pop esi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp, ebp
+ 0x5D, // pop ebp
+ 0xC3, // ret
+ 0x68, 0x00, 0x21, 0x40, 0x00, // push 00402100
+ 0xFF, 0x15, 0xA0, 0x20, 0x40, 0x00, // call dword ptr [004020A0]
+ 0x83, 0xC4, 0x04, // add esp, 04
+ 0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
+ 0xB8, 0x51, 0x10, 0x40, 0x00, // mov eax, 00401051
+ 0xC3, // ret
+ 0x8B, 0x54, 0x24, 0x08, // mov edx, [esp+08]
+ 0x8D, 0x42, 0x0C, // lea eax, [edx+0C]
+ 0x8B, 0x4A, 0xEC, // mov ecx, [edx-14]
+ 0x33, 0xC8, // xor ecx, eax
+ 0xE8, 0xE3, 0xF7, 0xFF, 0xFF, // call 00401094
+ 0xB8, 0xD0, 0x10, 0x40, 0x00, // mov eax, 004010D0
+ 0xE9, 0xD3, 0xFF, 0xFF, 0xFF, // jmp 0040188E
+ 0xCD, 0xCD, 0xCD, // alignment
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x63, 0x10, 0x40, 0x00, // dd 00401063
+ 0xFF, 0xFF, 0xFF, 0xFF, // dd FFFFFFFF
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0xFF, 0xFF, 0xFF, 0xFF, // dd FFFFFFFF
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x01, 0x00, 0x00, 0x00, // dd 00000001
+ 0x01, 0x00, 0x00, 0x00, // dd 00000001
+ 0x9C, 0x10, 0x40, 0x00, // dd 0040109C
+ 0x22, 0x05, 0x93, 0x19, // dd 19930522
+ 0x02, 0x00, 0x00, 0x00, // dd 00000002
+ 0xAC, 0x10, 0x40, 0x00, // dd 004010AC
+ 0x01, 0x00, 0x00, 0x00, // dd 00000001
+ 0xBC, 0x10, 0x40, 0x00, // dd 004010BC
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ 0x00, 0x00, 0x00, 0x00, // dd 00000000
+ };
+
+ ICommand *command;
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 64ul);
+ command = func->GetCommandByAddress(0x004010a8);
+ EXPECT_EQ(command->text(), "dd 00401063");
+ EXPECT_EQ(command->link()->type(), ltExtSEHHandler);
+ // Check CompileToNative
+ std::vector<uint8_t> data;
+ size_t i, j;
+ for (i = 0; i < func->count(); i++) {
+ command = func->item(i);
+ if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
+ continue;
+
+ data.clear();
+ for (j = 0; j < command->dump_size(); j++) {
+ data.push_back(command->dump(j));
+ }
+ command->CompileToNative();
+ EXPECT_EQ(command->dump_size(), data.size());
+ for (j = 0; j < command->dump_size(); j++) {
+ EXPECT_EQ(command->dump(j), data[j]);
+ }
+ }
+ // Check the compilation prepare
+ MemoryManager manager(&arch);
+ CompileContext ctx;
+ ctx.file = &arch;
+ ctx.manager = &manager;
+ ASSERT_TRUE(func->Prepare(ctx));
+ ASSERT_TRUE(func->PrepareExtCommands(ctx));
+ ASSERT_EQ(manager.count(), 1ul);
+ MemoryRegion *region = manager.item(0);
+ EXPECT_EQ(region->address(), 0x00401005ull);
+ EXPECT_EQ(region->size(), 0x79ul);
+ EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
+}
+
+TEST(IntelTest, x86_FPU)
+{
+ uint8_t buf[] = {
+ 0x9B, 0xD9, 0x7D, 0xFC, // fstcw [ebp - 4]
+ 0x9B, 0xDD, 0x7D, 0xFC, // fstsw [ebp - 4]
+ 0x9B, // wait
+ 0x90, // nop
+ 0xD9, 0x7D, 0xFC, // fnstcw [ebp - 4]
+ 0xDD, 0x7D, 0xFC, // fnstsw [ebp - 4]
+ 0xC3, // ret
+ 0xCD, 0xCD, 0xCD, 0xCD, // alignment
+ };
+
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 7ul);
+ EXPECT_EQ(func->item(0)->text(), "fstcw word ptr [ebp-04]");
+ EXPECT_EQ(func->item(1)->text(), "fstsw word ptr [ebp-04]");
+ EXPECT_EQ(func->item(4)->text(), "fnstcw word ptr [ebp-04]");
+ EXPECT_EQ(func->item(5)->text(), "fnstsw word ptr [ebp-04]");
+}
+
+TEST(IntelTest, x86_DisasmBranch1)
+{
+ uint8_t buf[] = {
+ 0x90, // nop
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0xC3, // ret
+ };
+
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 2ul);
+}
+
+TEST(IntelTest, x86_DisasmBranch2)
+{
+ uint8_t buf[] = {
+ 0x90, // nop
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0x90, // nop
+ 0x90, // nop
+ 0x90, // nop
+ 0x90, // nop
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0x0F, 0x84, 0xF3, 0xFF, 0xFF, 0xFF, // jz -13
+ 0x90, // nop
+ 0xC3, // ret
+ };
+
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 2ul);
+}
+
+TEST(IntelTest, x86_DisasmBranch3)
+{
+ uint8_t buf[] = {
+ 0x90, // nop
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0x90, // nop
+ 0x0F, 0x84, 0xF2, 0xFF, 0xFF, 0xFF, // jz -14
+ 0x90, // nop
+ 0x90, // nop
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0x0F, 0x84, 0xF3, 0xFF, 0xFF, 0xFF, // jz -13
+ 0x90, // nop
+ 0xC3, // ret
+ };
+
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 10ul);
+}
+
+TEST(IntelTest, x86_DisasmBranch4)
+{
+ uint8_t buf[] = {
+ 0x90, // nop
+ 0xE9, 0x03, 0x00, 0x00, 0x00, // jmp +3
+ 0xCC, // --
+ 0x90, // nop
+ 0x90, // nop
+ 0x90, // nop
+ 0x90, // nop
+ 0x0F, 0x84, 0xF6, 0xFF, 0xFF, 0xFF, // jz -10
+ 0x90, // nop
+ 0x90, // nop
+ 0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
+ 0xCC, // --
+ 0x0F, 0x84, 0xF3, 0xFF, 0xFF, 0xFF, // jz -13
+ 0x90, // nop
+ 0xC3, // ret
+ };
+
+ IntelFunction *func;
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(sizeof(buf));
+ test_file.OpenFromMemory(buf, sizeof(buf));
+ func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
+ ASSERT_EQ(func->count(), 13ul);
+}
+
+#ifdef _WIN32
+void CompileFunction(void *src, void *dest)
+{
+ uint8_t *buf = reinterpret_cast<uint8_t *>(src);
+ if (buf[0] == 0xe9) {
+ // jmp
+ uint32_t dw = *reinterpret_cast<uint32_t*>(&buf[1]);
+ buf = &buf[dw + 5];
+ }
+ TestFile test_file(osDWord);
+ IArchitecture &arch = *test_file.item(0);
+ TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
+ TestSegment *segment = segment_list->Add(reinterpret_cast<uint64_t>(dest), 0x1000, ".text", mtReadable | mtExecutable);
+ segment->set_physical_size(static_cast<uint32_t>(segment->size()));
+ test_file.OpenFromMemory(buf, static_cast<uint32_t>(0x1000 - 0x100));
+ IntelFunction *func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment->address(), ctVirtualization, 0, true, NULL));
+ for (size_t i = 0; i < func->count(); i++) {
+ IntelCommand *command = func->item(i);
+
+ if (command->type() == cmCall)
+ command->set_operand_value(0, command->operand(0).value + reinterpret_cast<uint64_t>(buf) - reinterpret_cast<uint64_t>(dest));
+ }
+ CompileOptions options;
+ options.flags = cpEncryptBytecode;
+ //int r = GetTickCount();
+ //printf("%d\n", r);
+ //srand(r);
+ arch.Compile(options, NULL);
+
+ arch.Seek(0);
+ arch.Read(dest, (size_t)arch.size());
+}
+
+void DoTestFunctionDWord(void *func_)
+{
+ void *address = VirtualAlloc(NULL, 0x20000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ ASSERT_TRUE(address != NULL);
+ CompileFunction(func_, address);
+
+ uint32_t orig_flags, flags;
+ uint32_t param1, param2, orig_res, res;
+ for (size_t i = 0; i < 100; i++) {
+ param1 = rand32();
+ param2 = rand32();
+ typedef uint32_t (tFunc)(uint32_t param1, uint32_t param2, uint32_t *flags);
+ orig_res = reinterpret_cast<tFunc *>(func_)(param1, param2, &orig_flags);
+ res = reinterpret_cast<tFunc *>(address)(param1, param2, &flags);
+ EXPECT_EQ(res, orig_res);
+ EXPECT_EQ(flags, orig_flags);
+ }
+
+ VirtualFree(address, 0, MEM_RELEASE);
+}
+
+void DoTestFunctionWord(void *func)
+{
+ void *address = VirtualAlloc(NULL, 0x20000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ ASSERT_TRUE(address != NULL);
+ CompileFunction(func, address);
+
+ uint32_t orig_flags, flags;
+ uint16_t param1, param2, orig_res, res;
+ for (size_t i = 0; i < 100; i++) {
+ param1 = rand();
+ param2 = rand();
+ typedef uint16_t (tFunc)(uint16_t param1, uint16_t param2, uint32_t *flags);
+ orig_res = reinterpret_cast<tFunc *>(func)(param1, param2, &orig_flags);
+ res = reinterpret_cast<tFunc *>(address)(param1, param2, &flags);
+ EXPECT_EQ(res, orig_res);
+ EXPECT_EQ(flags, orig_flags);
+ }
+
+ VirtualFree(address, 0, MEM_RELEASE);
+}
+
+void DoTestFunctionByte(void *func)
+{
+ void *address = VirtualAlloc(NULL, 0x20000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ ASSERT_TRUE(address != NULL);
+ CompileFunction(func, address);
+
+ uint32_t orig_flags, flags;
+ uint8_t param1, param2, orig_res;
+ for (size_t i = 0; i < 100; i++) {
+ param1 = rand();
+ param2 = rand();
+ typedef uint8_t (tFunc)(uint8_t param1, uint8_t param2, uint32_t *flags);
+ orig_res = reinterpret_cast<tFunc *>(func)(param1, param2, &orig_flags);
+ EXPECT_EQ(reinterpret_cast<tFunc *>(address)(param1, param2, &flags), orig_res);
+ EXPECT_EQ(flags, orig_flags);
+ }
+
+ VirtualFree(address, 0, MEM_RELEASE);
+}
+
+#ifndef _WIN64
+uint32_t AddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ add eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t AddWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ add ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t AddByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ add al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationAdd)
+{
+ DoTestFunctionDWord(&AddDWord);
+ DoTestFunctionWord(&AddWord);
+ DoTestFunctionByte(&AddByte);
+}
+
+uint32_t AdcDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ adc eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t AdcWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ adc ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t AdcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ adc al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationAdc)
+{
+ DoTestFunctionDWord(&AdcDWord);
+ DoTestFunctionWord(&AdcWord);
+ DoTestFunctionByte(&AdcByte);
+}
+
+uint32_t SubDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ sub eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t SubWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ sub ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t SubByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ sub al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationSub)
+{
+ DoTestFunctionDWord(&SubDWord);
+ DoTestFunctionWord(&SubWord);
+ DoTestFunctionByte(&SubByte);
+}
+
+uint32_t SbbDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ sbb eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t SbbWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ sbb ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t SbbByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ sbb al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationSbb)
+{
+ DoTestFunctionDWord(&SbbDWord);
+ DoTestFunctionWord(&SbbWord);
+ DoTestFunctionByte(&SbbByte);
+}
+
+uint32_t CmpDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ cmp eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t CmpWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ cmp ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t CmpByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ cmp al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationCmp)
+{
+ DoTestFunctionDWord(&CmpDWord);
+ DoTestFunctionWord(&CmpWord);
+ DoTestFunctionByte(&CmpByte);
+}
+
+uint32_t ShlDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ shl eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t ShlWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ shl ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t ShlByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ shl al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationShl)
+{
+ DoTestFunctionDWord(&ShlDWord);
+ DoTestFunctionWord(&ShlWord);
+ DoTestFunctionByte(&ShlByte);
+}
+
+uint32_t ShrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ shr eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t ShrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ shr ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t ShrByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ shr al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationShr)
+{
+ DoTestFunctionDWord(&ShrDWord);
+ DoTestFunctionWord(&ShrWord);
+ DoTestFunctionByte(&ShrByte);
+}
+
+uint32_t RolDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ rol eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t RolWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ rol ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t RolByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ rol al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationRol)
+{
+ DoTestFunctionDWord(&RolDWord);
+ DoTestFunctionWord(&RolWord);
+ DoTestFunctionByte(&RolByte);
+}
+
+uint32_t RorDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ ror eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t RorWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ ror ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t RorByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ ror al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationRor)
+{
+ DoTestFunctionDWord(&RorDWord);
+ DoTestFunctionWord(&RorWord);
+ DoTestFunctionByte(&RorByte);
+}
+
+uint32_t SarDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ sar eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t SarWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ sar ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t SarByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ sar al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and eax, ~fl_A
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationSar)
+{
+ DoTestFunctionDWord(&SarDWord);
+ DoTestFunctionWord(&SarWord);
+ DoTestFunctionByte(&SarByte);
+}
+
+uint32_t RclDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ rcl eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t RclWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ rcl ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t RclByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ rcl al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationRcl)
+{
+ DoTestFunctionDWord(&RclDWord);
+ DoTestFunctionWord(&RclWord);
+ DoTestFunctionByte(&RclByte);
+}
+
+uint32_t RcrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ rcr eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t RcrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ rcr ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t RcrByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ rcr al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ and cl, 31
+ jnz label_1
+ xor eax, eax
+label_1:
+ cmp cl, 1
+ jz label_2
+ and eax, ~fl_O
+label_2:
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationRcr)
+{
+ DoTestFunctionDWord(&RcrDWord);
+ DoTestFunctionWord(&RcrWord);
+ DoTestFunctionByte(&RcrByte);
+}
+
+uint32_t XorDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ xor eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t XorWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ xor ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t XorByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ xor al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationXor)
+{
+ DoTestFunctionDWord(&XorDWord);
+ DoTestFunctionWord(&XorWord);
+ DoTestFunctionByte(&XorByte);
+}
+
+uint32_t OrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ or eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t OrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ or ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t OrByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ or al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationOr)
+{
+ DoTestFunctionDWord(&OrDWord);
+ DoTestFunctionWord(&OrWord);
+ DoTestFunctionByte(&OrByte);
+}
+
+uint32_t AndDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ and eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t AndWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ and ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t AndByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ and al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationAnd)
+{
+ DoTestFunctionDWord(&AndDWord);
+ DoTestFunctionWord(&AndWord);
+ DoTestFunctionByte(&AndByte);
+}
+
+uint32_t TestDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ test eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t TestWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ test ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t TestByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ test al, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationTest)
+{
+ DoTestFunctionDWord(&TestDWord);
+ DoTestFunctionWord(&TestWord);
+ DoTestFunctionByte(&TestByte);
+}
+
+uint32_t NotDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ not eax
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t NotWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ not ax
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t NotByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ not al
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationNot)
+{
+ DoTestFunctionDWord(&NotDWord);
+ DoTestFunctionWord(&NotWord);
+ DoTestFunctionByte(&NotByte);
+}
+
+uint32_t NegDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ neg eax
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t NegWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ neg ax
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t NegByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ neg al
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationNeg)
+{
+ DoTestFunctionDWord(&NegDWord);
+ DoTestFunctionWord(&NegWord);
+ DoTestFunctionByte(&NegByte);
+}
+
+uint32_t XaddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ xadd res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t XaddWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ mov res, ax
+
+ xadd res, cx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t XaddByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ mov res, al
+
+ xadd res, cl
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationXadd)
+{
+ DoTestFunctionDWord(&XaddDWord);
+ DoTestFunctionWord(&XaddWord);
+ DoTestFunctionByte(&XaddByte);
+}
+
+uint32_t XchgDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ xchg eax, ecx
+
+ mov res, eax
+ cmp eax, param1
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t XchgWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+
+ xchg ax, cx
+
+ mov res, ax
+ cmp ax, param1
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t XchgByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ xchg al, cl
+
+ mov res, al
+ cmp al, param1
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationXchg)
+{
+ DoTestFunctionDWord(&XchgDWord);
+ DoTestFunctionWord(&XchgWord);
+ DoTestFunctionByte(&XchgByte);
+}
+
+uint32_t IncDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ inc eax
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t IncWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ inc ax
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t IncByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ inc al
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationInc)
+{
+ DoTestFunctionDWord(&IncDWord);
+ DoTestFunctionWord(&IncWord);
+ DoTestFunctionByte(&IncByte);
+}
+
+uint32_t DecDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ dec eax
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t DecWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ dec ax
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t DecByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ dec al
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationDec)
+{
+ DoTestFunctionDWord(&DecDWord);
+ DoTestFunctionWord(&DecWord);
+ DoTestFunctionByte(&DecByte);
+}
+
+uint32_t MulDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ push edx
+ mov eax, param1
+ mov ecx, param2
+
+ mul ecx
+
+ pushfd
+ add eax, edx
+ mov res, eax
+ pop eax
+ and eax, ~(fl_S | fl_Z | fl_A | fl_P)
+ mov ecx, flags
+ mov [ecx], eax
+ pop edx
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t MulWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ push edx
+ mov ax, param1
+
+ mul param2
+
+ pushfd
+ add ax, dx
+ mov res, ax
+ pop eax
+ and eax, ~(fl_S | fl_Z | fl_A | fl_P)
+ mov ecx, flags
+ mov [ecx], eax
+ pop edx
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t MulByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ mul cl
+
+ pushfd
+ add al, ah
+ mov res, al
+ pop eax
+ and eax, ~(fl_S | fl_Z | fl_A | fl_P)
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationMul)
+{
+ DoTestFunctionDWord(&MulDWord);
+ DoTestFunctionWord(&MulWord);
+ DoTestFunctionByte(&MulByte);
+}
+
+uint32_t ImulDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ push edx
+ mov eax, param1
+ mov ecx, param2
+
+ imul ecx
+
+ pushfd
+ add eax, edx
+ mov res, eax
+ pop eax
+ and eax, ~(fl_S | fl_Z | fl_A | fl_P)
+ mov ecx, flags
+ mov [ecx], eax
+ pop edx
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t ImulWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ push edx
+ mov ax, param1
+
+ imul param2
+
+ pushfd
+ add ax, dx
+ mov res, ax
+ pop eax
+ and eax, ~(fl_S | fl_Z | fl_A | fl_P)
+ mov ecx, flags
+ mov [ecx], eax
+ pop edx
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t ImulByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+
+ imul cl
+
+ pushfd
+ add al, ah
+ mov res, al
+ pop eax
+ and eax, ~(fl_S | fl_Z | fl_A | fl_P)
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationImul)
+{
+ DoTestFunctionDWord(&ImulDWord);
+ DoTestFunctionWord(&ImulWord);
+ DoTestFunctionByte(&ImulByte);
+}
+
+uint32_t BtDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ bt eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ bt ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t BtMemDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ and ecx, 0x1f
+
+ bt param1, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtMemWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ and ecx, 0x0f
+
+ bt param1, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t BtValDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ and ecx, 0x1f
+
+ bt param1, 0x18
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtValWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ and ecx, 0x0f
+
+ bt param1, 8
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationBt)
+{
+ DoTestFunctionDWord(&BtDWord);
+ DoTestFunctionWord(&BtWord);
+ DoTestFunctionDWord(&BtMemDWord);
+ DoTestFunctionWord(&BtMemWord);
+ DoTestFunctionDWord(&BtValDWord);
+ DoTestFunctionWord(&BtValWord);
+}
+
+uint32_t BtsDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ bts eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtsWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ bts ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t BtsMemDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ and ecx, 0x1f
+
+ bts param1, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtsMemWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ and ecx, 0x0f
+
+ bts param1, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationBts)
+{
+ DoTestFunctionDWord(&BtsDWord);
+ DoTestFunctionWord(&BtsWord);
+ DoTestFunctionDWord(&BtsMemDWord);
+ DoTestFunctionWord(&BtsMemWord);
+}
+
+uint32_t BtrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ btr eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ btr ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationBtr)
+{
+ DoTestFunctionDWord(&BtrDWord);
+ DoTestFunctionWord(&BtrWord);
+}
+
+uint32_t BtcDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ btc eax, cl
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t BtcWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ btc ax, cl
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationBtc)
+{
+ DoTestFunctionDWord(&BtcDWord);
+ DoTestFunctionWord(&BtcWord);
+}
+
+uint32_t CmovDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ cmp al, cl
+
+ cmovc eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t CmovWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ cmp al, cl
+
+ cmovna ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationCmov)
+{
+ DoTestFunctionDWord(&CmovDWord);
+ DoTestFunctionWord(&CmovWord);
+}
+
+uint32_t LockAddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ lock add res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint16_t LockAddWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ax, param1
+ mov cx, param2
+ mov res, ax
+
+ lock add res, cx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t LockAddByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ mov res, al
+
+ lock add res, cl
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LockSubDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ lock sub res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LockXorDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ lock xor res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LockAndDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ lock and res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LockOrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ lock or res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LockXchgDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+ cmp eax, ecx
+
+ lock xchg res, ecx
+ mov res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LockXaddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ mov res, eax
+
+ lock xadd res, ecx
+ xor res, ecx
+
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationLock)
+{
+ DoTestFunctionDWord(&LockAddDWord);
+ DoTestFunctionWord(&LockAddWord);
+ DoTestFunctionByte(&LockAddByte);
+ DoTestFunctionDWord(&LockAndDWord);
+ DoTestFunctionDWord(&LockSubDWord);
+ DoTestFunctionDWord(&LockXorDWord);
+ DoTestFunctionDWord(&LockOrDWord);
+ DoTestFunctionDWord(&LockXchgDWord);
+ DoTestFunctionDWord(&LockXaddDWord);
+}
+
+uint32_t CbxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+
+ cbw
+ movzx ecx, ax
+ mov eax, param2
+ cwd
+ add eax, ecx
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t MovzxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+
+ lea ecx, param1
+ movzx eax, byte ptr [ecx + 1]
+ movzx ecx, word ptr [ecx + 2]
+
+ add eax, ecx
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t MovsxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ movsx ecx, cl
+ movsx eax, ax
+
+ add eax, ecx
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t LahfByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov al, param1
+ mov cl, param2
+ cmp al, cl
+
+ lahf
+
+ mov res, ah
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t SahfByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov ah, param1
+
+ sahf
+
+ mov res, ah
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t StcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ xor eax, eax
+
+ stc
+
+ setc res
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t ClcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, -1
+ inc eax
+
+ clc
+
+ setc res
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint8_t CmcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, -1
+ inc eax
+
+ cmc
+
+ setc res
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+
+uint8_t XlatByte(uint8_t param1, uint8_t param2, uint32_t *flags)
+{
+ uint8_t res;
+ uint8_t xlat_table[0x100];
+ for (size_t i = 0; i < 0x100; i++)
+ xlat_table[(uint8_t)i] = 0x100 - (uint8_t)i;
+ _asm {
+ push eax
+ push ecx
+
+ lea ebx, xlat_table
+ mov al, param1
+ xlat
+ add al, param2
+ xlat
+
+ mov res, al
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov[ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t BswapDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+
+ bswap eax
+
+ mov res, eax
+ add eax, param2
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LeaDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+
+ lea eax, [ecx+eax*4+0x10000]
+
+ mov res, eax
+ xor eax, param2
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t ESPDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push eax
+ push ecx
+
+ mov eax, param1
+ mov [esp+4], eax
+ cmp eax, [esp+4]
+
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ pop eax
+ }
+ return res;
+}
+
+uint16_t SegWord(uint16_t param1, uint16_t param2, uint32_t *flags)
+{
+ uint16_t res;
+ _asm {
+ push eax
+ push ecx
+
+ push ss
+ pop eax
+
+ mov cx, ds
+ cmp ax, cx
+
+ mov res, ax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LodsDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ push edi
+
+ lea esi, param1
+ lodsd
+ mov res, eax
+
+ mov ecx, flags
+ mov [ecx], esi
+ pop edi
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t RepStosDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ push edi
+
+ mov eax, param1
+ mov ecx, 4
+ lea edi, res
+ rep stosb
+
+ mov eax, ecx
+ mov ecx, flags
+ mov [ecx], eax
+ pop edi
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LdsDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ uint8_t mem[6];
+
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ lea ecx, mem
+ mov [ecx], eax
+ mov ax, ds
+ mov [ecx+4], ax
+
+ lds eax, mem
+
+ mov res, ecx
+ cmp eax, ecx
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t PopESPDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ push edi
+
+ mov edi, esp
+ mov eax, param1
+ mov ecx, param2
+ push 0
+ push 0
+ xchg [esp], eax
+ pop dword ptr [esp]
+ pop eax
+ sub edi, esp
+
+ mov res, eax
+ mov ecx, flags
+ mov [ecx], edi
+ pop edi
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationOther)
+{
+ DoTestFunctionDWord(&CbxDWord);
+ DoTestFunctionDWord(&MovzxDWord);
+ DoTestFunctionDWord(&MovsxDWord);
+ DoTestFunctionByte(&LahfByte);
+ DoTestFunctionByte(&SahfByte);
+ DoTestFunctionByte(&StcByte);
+ DoTestFunctionByte(&ClcByte);
+ DoTestFunctionByte(&CmcByte);
+ DoTestFunctionDWord(&BswapDWord);
+ DoTestFunctionDWord(&LeaDWord);
+ DoTestFunctionDWord(&ESPDWord);
+ DoTestFunctionWord(&SegWord);
+ DoTestFunctionDWord(&LodsDWord);
+ DoTestFunctionDWord(&RepStosDWord);
+ DoTestFunctionDWord(&LdsDWord);
+ DoTestFunctionDWord(&PopESPDWord);
+ DoTestFunctionByte(&XlatByte);
+}
+
+uint32_t WriteStackDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ push edi
+
+ mov edi, esp
+ push ecx
+ mov [edi-4], eax
+ mov eax, [edi-4]
+ mov esp, edi
+
+ mov res, eax
+ mov ecx, flags
+ mov [ecx], edi
+ pop edi
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t ReadStackDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ push edi
+
+ mov edi, esp
+ push ecx
+ mov eax, [edi-4]
+ mov esp, edi
+
+ mov res, eax
+ mov ecx, flags
+ mov [ecx], edi
+ pop edi
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationStack)
+{
+ DoTestFunctionDWord(&ReadStackDWord);
+ DoTestFunctionDWord(&WriteStackDWord);
+}
+
+uint32_t JxxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+
+ cmp eax, param2
+ jnl label_0
+ not eax
+label_0:
+ test eax, 1
+ jnz label_1
+ add eax, param2
+ jc label_2
+ or al, 1
+ jmp label_0
+label_2:
+ rol eax, 1
+
+label_1:
+ mov res, eax
+ pushfd
+ pop eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LoopDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ movzx ecx, cl
+
+ jecxz label_1
+label_0:
+ add eax, eax
+ loop label_0
+
+label_1:
+ mov res, eax
+ mov eax, ecx
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LoopeDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ movzx ecx, cl
+
+ jecxz label_1
+label_0:
+ add eax, eax
+ test ah, 1
+ loope label_0
+
+label_1:
+ mov res, eax
+ mov eax, ecx
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t LoopneDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+ mov eax, param1
+ mov ecx, param2
+ movzx ecx, cl
+
+ jecxz label_1
+label_0:
+ add eax, eax
+ test ah, 1
+ loopne label_0
+
+label_1:
+ mov res, eax
+ mov eax, ecx
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+uint32_t RetDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
+{
+ uint32_t res;
+ _asm {
+ push eax
+ push ecx
+
+ push cs
+ mov eax, offset(label_1)
+ push eax
+ retf
+
+label_1:
+ mov eax, param1
+ mov res, eax
+ mov ecx, flags
+ mov [ecx], eax
+ pop ecx
+ pop eax
+ }
+ return res;
+}
+
+TEST(IntelTest, VirtualizationBranches)
+{
+ DoTestFunctionDWord(&JxxDWord);
+ DoTestFunctionDWord(&LoopDWord);
+ DoTestFunctionDWord(&LoopeDWord);
+ DoTestFunctionDWord(&LoopneDWord);
+ DoTestFunctionDWord(&RetDWord);
+ DoTestFunctionDWord(&CmovDWord);
+}
+#endif //_WIN64
+#endif //_WIN32