summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-01-28 09:58:23 +0100
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-01-28 09:58:23 +0100
commitf08280eb5759350b2bc22a0ae901184ffc7bd80f (patch)
tree99d0690559b3a7176d4fcb920023e03d37ff1839
parent73482b5dd2f8bacc019c8db2a563f45f81961686 (diff)
Asm: Improved AMD64 support for i64asm.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
-rw-r--r--Private/CompilerKit/AsmKit/Arch/amd64.hpp14
-rw-r--r--Private/CompilerKit/AsmKit/AsmKit.hpp69
-rw-r--r--Private/Toolchain/64asm.cc15
-rw-r--r--Private/Toolchain/bin/Source/hello_amd64.masm8
-rw-r--r--Private/Toolchain/i64asm.cc601
-rw-r--r--Public/PDF/ASM_86.TXT1
6 files changed, 613 insertions, 95 deletions
diff --git a/Private/CompilerKit/AsmKit/Arch/amd64.hpp b/Private/CompilerKit/AsmKit/Arch/amd64.hpp
index 239bdca..ac92c9b 100644
--- a/Private/CompilerKit/AsmKit/Arch/amd64.hpp
+++ b/Private/CompilerKit/AsmKit/Arch/amd64.hpp
@@ -45,12 +45,19 @@ struct CpuCodeAMD64
#define kJumpLimitStandardLimit 0xEB
inline std::vector<CpuCodeAMD64> kOpcodesAMD64 = {
- kAsmOpcodeDecl("int", 0xE3)
+ kAsmOpcodeDecl("int", 0xCD)
kAsmOpcodeDecl("into", 0xCE)
+ kAsmOpcodeDecl("intd", 0xF1)
+ kAsmOpcodeDecl("int3", 0xC3)
+
kAsmOpcodeDecl("iret", 0xCF)
- kAsmOpcodeDecl("ret", 0xC3)
+ kAsmOpcodeDecl("retf", 0xCB)
+ kAsmOpcodeDecl("retn", 0xC3)
kAsmOpcodeDecl("sti", 0xfb)
kAsmOpcodeDecl("cli", 0xfa)
+
+ kAsmOpcodeDecl("nop", 0x90)
+
kAsmOpcodeDecl("mov eax", 0xb8)
kAsmOpcodeDecl("mov ecx", 0xb9)
kAsmOpcodeDecl("mov edx", 0xba)
@@ -58,8 +65,11 @@ inline std::vector<CpuCodeAMD64> kOpcodesAMD64 = {
kAsmOpcodeDecl("mov esp", 0xbc)
kAsmOpcodeDecl("mov ebp", 0xbd)
kAsmOpcodeDecl("mov esi", 0xbe)
+
kAsmOpcodeDecl("jmp", 0xE9)
kAsmOpcodeDecl("call", 0xE9)
+
+ kAsmOpcodeDecl("mov", 0x00)
};
// \brief 64x0 register prefix
diff --git a/Private/CompilerKit/AsmKit/AsmKit.hpp b/Private/CompilerKit/AsmKit/AsmKit.hpp
index cc8940e..a561aad 100644
--- a/Private/CompilerKit/AsmKit/AsmKit.hpp
+++ b/Private/CompilerKit/AsmKit/AsmKit.hpp
@@ -61,6 +61,53 @@ namespace CompilerKit
};
+ union NumberCastBase
+ {
+ NumberCastBase() = default;
+ ~NumberCastBase() = default;
+
+ };
+
+ union NumberCast64 final
+ {
+ NumberCast64() = default;
+ explicit NumberCast64(UInt64 raw) : raw(raw) {}
+ ~NumberCast64() { raw = 0; }
+
+ CharType number[8];
+ UInt64 raw;
+ };
+
+ union NumberCast32 final
+ {
+ NumberCast32() = default;
+ explicit NumberCast32(UInt32 raw) : raw(raw) {}
+ ~NumberCast32() { raw = 0; }
+
+ CharType number[4];
+ UInt32 raw;
+ };
+
+ union NumberCast16 final
+ {
+ NumberCast16() = default;
+ explicit NumberCast16(UInt16 raw) : raw(raw) {}
+ ~NumberCast16() { raw = 0; }
+
+ CharType number[2];
+ UInt16 raw;
+ };
+
+ union NumberCast8 final
+ {
+ NumberCast8() = default;
+ explicit NumberCast8(UInt8 raw) : raw(raw) {}
+ ~NumberCast8() { raw = 0; }
+
+ CharType number;
+ UInt8 raw;
+ };
+
class PlatformAssembler
{
public:
@@ -89,6 +136,10 @@ namespace CompilerKit
virtual bool WriteLine(std::string &line, const std::string &file) override;
virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override;
+ virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what);
+ virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what);
+ virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what);
+
};
#endif // __ASM_NEED_AMD64__
@@ -128,23 +179,5 @@ namespace CompilerKit
};
#endif // __ASM_NEED_32x0__
-
- union NumberCast final
- {
- explicit NumberCast(UInt64 raw) : raw(raw) {}
- ~NumberCast() { raw = 0; }
-
- CharType number[8];
- UInt64 raw;
- };
-
- union NumberCast32 final
- {
- explicit NumberCast32(UInt32 raw) : raw(raw) {}
- ~NumberCast32() { raw = 0; }
-
- CharType number[4];
- UInt32 raw;
- };
}
diff --git a/Private/Toolchain/64asm.cc b/Private/Toolchain/64asm.cc
index 3bd0eda..2764bf0 100644
--- a/Private/Toolchain/64asm.cc
+++ b/Private/Toolchain/64asm.cc
@@ -309,10 +309,7 @@ MPCC_MODULE(MPUXAssembler64000)
// byte from byte, we write this.
for (auto& byte : kBytes)
{
- for (size_t i = 0; i < sizeof(byte); i++)
- {
- file_ptr_out << reinterpret_cast<const char*>(&byte)[i];
- }
+ file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte));
}
if (kVerbose)
@@ -662,7 +659,7 @@ bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, std
}
}
- CompilerKit::NumberCast num(strtoq(jump_label.substr(pos + 2).c_str(),
+ CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos + 2).c_str(),
nullptr, 16));
for (char &i : num.number)
@@ -690,7 +687,7 @@ bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, std
}
}
- CompilerKit::NumberCast num(strtoq(jump_label.substr(pos + 2).c_str(),
+ CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos + 2).c_str(),
nullptr, 2));
if (kVerbose)
@@ -718,7 +715,7 @@ bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, std
}
}
- CompilerKit::NumberCast num(strtoq(jump_label.substr(pos + 2).c_str(),
+ CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos + 2).c_str(),
nullptr, 7));
if (kVerbose)
@@ -750,7 +747,7 @@ bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, std
}
}
- CompilerKit::NumberCast num(strtoq(jump_label.substr(pos).c_str(),
+ CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos).c_str(),
nullptr, 10));
for (char &i : num.number)
@@ -1017,7 +1014,7 @@ bool CompilerKit::PlatformAssembler64x0::WriteLine(std::string &line, const std:
<< std::endl;
}
- CompilerKit::NumberCast num(label.second);
+ CompilerKit::NumberCast64 num(label.second);
for (auto &num : num.number)
{
diff --git a/Private/Toolchain/bin/Source/hello_amd64.masm b/Private/Toolchain/bin/Source/hello_amd64.masm
index 84010aa..0e79a99 100644
--- a/Private/Toolchain/bin/Source/hello_amd64.masm
+++ b/Private/Toolchain/bin/Source/hello_amd64.masm
@@ -3,5 +3,9 @@ bits 64
export .text MySampleFoo
cli
-mov edx, 0x1000
-ret \ No newline at end of file
+mov rsp, rdx
+int 0x80
+jmp 0x100000
+sti
+retf
+
diff --git a/Private/Toolchain/i64asm.cc b/Private/Toolchain/i64asm.cc
index 7ebe06c..f23c3e9 100644
--- a/Private/Toolchain/i64asm.cc
+++ b/Private/Toolchain/i64asm.cc
@@ -642,109 +642,381 @@ bool CompilerKit::PlatformAssemblerAMD64::WriteNumber(const std::size_t &pos, st
switch (jump_label[pos + 1])
{
- case 'x':
- {
- if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
- nullptr, 16);
- !res)
+ case 'x':
{
- if (errno != 0)
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid hex number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16));
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose)
{
- detail::print_error("invalid hex number: " + jump_label, "i64asm");
- throw std::runtime_error("invalid_hex");
+ kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n";
}
+
+ return true;
}
+ case 'b':
+ {
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid binary number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
- CompilerKit::NumberCast32 num(strtoq(jump_label.substr(pos + 2).c_str(),
- nullptr, 16));
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
- for (char &i : num.number)
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o':
{
- if (i == 0)
- i = 0xFF;
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid octal number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
- kBytes.push_back(i);
+ CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ return true;
}
+ default:
+ {
+ break;
+ }
+ }
- if (kVerbose)
+ /* check for errno and stuff like that */
+ if (auto res = strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10);
+ !res)
+ {
+ if (errno != 0)
{
- kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n";
+ return false;
}
+ }
- return true;
+ CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10));
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
}
- case 'b':
+
+ if (kVerbose)
{
- if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
- nullptr, 2);
- !res)
+ kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+}
+
+bool CompilerKit::PlatformAssemblerAMD64::WriteNumber32(const std::size_t &pos, std::string &jump_label)
+{
+ if (!isdigit(jump_label[pos]))
+ return false;
+
+ switch (jump_label[pos + 1])
+ {
+ case 'x':
{
- if (errno != 0)
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16);
+ !res)
{
- detail::print_error("invalid binary number: " + jump_label, "i64asm");
- throw std::runtime_error("invalid_bin");
+ if (errno != 0)
+ {
+ detail::print_error("invalid hex number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_hex");
+ }
}
- }
- CompilerKit::NumberCast32 num(strtoq(jump_label.substr(pos + 2).c_str(),
- nullptr, 2));
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16));
- if (kVerbose)
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b':
{
- kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid binary number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ return true;
}
+ case 'o':
+ {
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid octal number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7));
- for (char &i : num.number)
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default:
{
- if (i == 0)
- i = 0xFF;
+ break;
+ }
+ }
- kBytes.push_back(i);
+ /* check for errno and stuff like that */
+ if (auto res = strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10);
+ !res)
+ {
+ if (errno != 0)
+ {
+ return false;
}
+ }
- return true;
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10));
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
}
- case 'o':
+
+ if (kVerbose)
{
- if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
- nullptr, 7);
- !res)
+ kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+}
+
+bool CompilerKit::PlatformAssemblerAMD64::WriteNumber16(const std::size_t &pos, std::string &jump_label)
+{
+ if (!isdigit(jump_label[pos]))
+ return false;
+
+ switch (jump_label[pos + 1])
+ {
+ case 'x':
{
- if (errno != 0)
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16);
+ !res)
{
- detail::print_error("invalid octal number: " + jump_label, "i64asm");
- throw std::runtime_error("invalid_octal");
+ if (errno != 0)
+ {
+ detail::print_error("invalid hex number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_hex");
+ }
}
- }
- CompilerKit::NumberCast32 num(strtoq(jump_label.substr(pos + 2).c_str(),
- nullptr, 7));
+ CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16));
- if (kVerbose)
- {
- kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n";
- }
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
- for (char &i : num.number)
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b':
{
- if (i == 0)
- i = 0xFF;
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid binary number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
- kBytes.push_back(i);
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ return true;
}
+ case 'o':
+ {
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid octal number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
- return true;
- }
- default:
- {
- break;
- }
+ CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ for (char &i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default:
+ {
+ break;
+ }
}
/* check for errno and stuff like that */
if (auto res = strtoq(jump_label.substr(pos).c_str(),
nullptr, 10);
- !res)
+ !res)
{
if (errno != 0)
{
@@ -752,8 +1024,8 @@ bool CompilerKit::PlatformAssemblerAMD64::WriteNumber(const std::size_t &pos, st
}
}
- CompilerKit::NumberCast32 num(strtoq(jump_label.substr(pos).c_str(),
- nullptr, 10));
+ CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10));
for (char &i : num.number)
{
@@ -771,6 +1043,118 @@ bool CompilerKit::PlatformAssemblerAMD64::WriteNumber(const std::size_t &pos, st
return true;
}
+bool CompilerKit::PlatformAssemblerAMD64::WriteNumber8(const std::size_t &pos, std::string &jump_label)
+{
+ if (!isdigit(jump_label[pos]))
+ return false;
+
+ switch (jump_label[pos + 1])
+ {
+ case 'x':
+ {
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid hex number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_hex");
+ }
+ }
+
+ CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 16));
+
+ kBytes.push_back(num.number);
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b':
+ {
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid binary number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_bin");
+ }
+ }
+
+ CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 2));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ kBytes.push_back(num.number);
+
+ return true;
+ }
+ case 'o':
+ {
+ if (auto res = strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7);
+ !res)
+ {
+ if (errno != 0)
+ {
+ detail::print_error("invalid octal number: " + jump_label, "i64asm");
+ throw std::runtime_error("invalid_octal");
+ }
+ }
+
+ CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos + 2).c_str(),
+ nullptr, 7));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ kBytes.push_back(num.number);
+
+ return true;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10);
+ !res)
+ {
+ if (errno != 0)
+ {
+ return false;
+ }
+ }
+
+ CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos).c_str(),
+ nullptr, 10));
+
+ kBytes.push_back(num.number);
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// @brief Read and write an instruction to the output array.
@@ -790,11 +1174,100 @@ bool CompilerKit::PlatformAssemblerAMD64::WriteLine(std::string &line, const std
{
std::string name(opcodeAMD64.fName);
- kBytes.emplace_back(opcodeAMD64.fOpcode);
-
if (name.find("mov") != std::string::npos)
{
- this->WriteNumber(line.find(name) + name.size() + 2, line);
+ struct RegMapAMD64 {
+ std::string fName;
+ e64_byte_t fModRM;
+ };
+
+ std::vector<RegMapAMD64> regs {
+ { .fName = "ax", .fModRM = 0 },
+ { .fName = "cx", .fModRM = 1 },
+ { .fName = "dx", .fModRM = 2 },
+ { .fName = "bx", .fModRM = 3 },
+ { .fName = "sp", .fModRM = 4 },
+ { .fName = "bp", .fModRM = 5 },
+ { .fName = "si", .fModRM = 6 },
+ { .fName = "di", .fModRM = 7 },
+ };
+
+ std::string substr = line.substr(line.find(name) + name.size());
+
+ uint64_t bits = 16;
+
+ if (substr.find(",") == std::string::npos)
+ {
+ detail::print_error("Invalid combination of operands and registers.", "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ bool found = false;
+
+ for (auto& reg : regs)
+ {
+ if (line.find(reg.fName) != std::string::npos)
+ {
+ if (!found)
+ {
+ if (line.substr(line.find(reg.fName) - 1)[0] == 'r')
+ {
+ bits = 64;
+
+ kBytes.emplace_back(0x48);
+ kBytes.emplace_back(0x89);
+ kBytes.emplace_back(0x00);
+ }
+ else
+ {
+ detail::print_error("Invalid combination of registers, each 64-bit register must start with 'r'.", "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ found = true;
+
+ kBytes.push_back(0xc0 + reg.fModRM);
+
+ continue;
+ }
+ }
+ }
+
+ if (bits == 64)
+ this->WriteNumber32(line.find(name) + name.size() + 2, line);
+ else if (bits == 16)
+ this->WriteNumber16(line.find(name) + name.size() + 2, line);
+ else
+ {
+ detail::print_error("Invalid combination of operands and registers.", "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ break;
+ }
+ else if (name == "int" ||
+ name == "into" ||
+ name == "intd")
+ {
+ kBytes.emplace_back(opcodeAMD64.fOpcode);
+ this->WriteNumber8(line.find(name) + name.size() + 1, line);
+
+ break;
+ }
+ else if (name == "jmp" ||
+ name == "call")
+ {
+ kBytes.emplace_back(opcodeAMD64.fOpcode);
+ this->WriteNumber32(line.find(name) + name.size() + 1, line);
+
+ break;
+ }
+ else
+ {
+ kBytes.emplace_back(0);
+ kBytes.emplace_back(opcodeAMD64.fOpcode);
+
+ break;
}
}
}
diff --git a/Public/PDF/ASM_86.TXT b/Public/PDF/ASM_86.TXT
index b7111be..8669eba 100644
--- a/Public/PDF/ASM_86.TXT
+++ b/Public/PDF/ASM_86.TXT
@@ -7,4 +7,5 @@
TODO:
Encode instructions [ X ]
+ Fix MOV ModRM [ ]
Extend instructions support [ ] \ No newline at end of file