forked from LHLaurini/fasmcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fasmcpp.win64.cpp
128 lines (102 loc) · 3.2 KB
/
fasmcpp.win64.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "fasmcpp.win64.h"
#include "fasmcpp.h"
#include "fasmFunctions.h"
#include <fstream>
#include <Windows.h>
fasmcpp::Assembler::Assembler()
{
_assemblerMemory = nullptr;
_assemblerMemorySize = 0;
}
fasmcpp::Assembler::Assembler(size_t memory, size_t predefinitionsMemory)
{
std::ifstream file("fasmcpp.win64.bin", std::ios::binary);
if (!file)
{
throw std::runtime_error("Fatal error: flat assembler binary not found.");
}
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0);
char* address = reinterpret_cast<char*>(WIN64_LOW_MEMORY_FIXED_ADDRESS);
if (address + size + memory + predefinitionsMemory > reinterpret_cast<char*>(0xFFFFFFFFUi64))
{
throw std::length_error("Error: the requested amount of assembler memory is too large and "
"cannot fit entirely in 32-bit memory.");
}
FasmBinaryHeader header;
char* headerPtr = reinterpret_cast<char*>(&header);
file.read(headerPtr, sizeof(header));
header.fasmError = fasmError;
header.fasmOpen = fasmOpen;
header.fasmRead = fasmRead;
header.fasmWrite = fasmWrite;
header.fasmClose = fasmClose;
header.fasmLseek = fasmLseek;
header.fasmDisplayBlock = fasmDisplayBlock;
size_t memoryQty = header._fasm_memory - address + memory + predefinitionsMemory;
if (!VirtualAlloc(address, memoryQty, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE))
{
throw std::runtime_error("Fatal error: failed to allocate memory for Flat Assembler.");
}
std::copy(headerPtr, headerPtr + sizeof(FasmBinaryHeader), address);
file.read(address + sizeof(FasmBinaryHeader), size - sizeof(FasmBinaryHeader));
_assemblerMemory = header._fasm_memory;
_assemblerMemorySize = static_cast<uint32_t>(memory);
_predefinitionsMemory = header._fasm_memory + memory;
_predefinitionsMemorySize = static_cast<uint32_t>(predefinitionsMemory);
}
fasmcpp::Assembler::~Assembler()
{
if (_assemblerMemory)
{
VirtualFree(reinterpret_cast<void*>(WIN64_LOW_MEMORY_FIXED_ADDRESS), 0, MEM_RELEASE);
_assemblerMemory = nullptr;
_assemblerMemorySize = 0;
}
}
void fasmcpp::Assembly::allocateExecutableMemory(size_t size)
{
void* memory = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (memory)
{
_executableMemory = memory;
_executableMemorySize = size;
}
else
{
throw std::runtime_error("Fatal error: failed to allocate executable memory.");
}
}
void fasmcpp::Assembly::freeExecutableMemory()
{
if (_executableMemory)
{
VirtualFree(_executableMemory, 0, MEM_RELEASE);
_executableMemory = nullptr;
}
}
const char* fasmcpp::Assembly::rebuildPredefinitionsString()
{
char* predefinitionsString = _assembler->getPredefinitionsMemory();
if (_predefinitionsChanged)
{
char* end = predefinitionsString;
ptrdiff_t memoryLeft = _assembler->getPredefinitionsMemorySize();
for (auto& i : _predefinitions)
{
memoryLeft -= i.first.size() + i.second.size() + 2;
if (memoryLeft < 1)
{
throw std::runtime_error("Error: out of predefinitions memory.");
}
*end++ = static_cast<char>(i.first.size());
std::copy(i.first.begin(), i.first.end(), end);
end += i.first.size();
strcpy(end, i.second.c_str());
end += i.second.size() + 1;
}
*end = 0;
}
return predefinitionsString;
}