summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-10-18 18:38:26 +0200
committerRoland Reichwein <mail@reichwein.it>2020-10-18 18:38:26 +0200
commitfe722b9304052b7a0a67fe01633c24ba5b4cdafa (patch)
tree7656b558c4dea8221bff07377253c66ec9f79086
parent8a2d1dc5c8b6639985d26d1c915048d87d52426b (diff)
Implemented insertAddresses()
-rw-r--r--asm/assembler.cpp2
-rw-r--r--asm/chunk.h2
-rw-r--r--asm/intel64/jmp.cpp6
-rw-r--r--asm/segment.cpp45
-rw-r--r--asm/segment.h1
-rw-r--r--test-asm.cpp22
6 files changed, 69 insertions, 9 deletions
diff --git a/asm/assembler.cpp b/asm/assembler.cpp
index 5c879b1..501c0a4 100644
--- a/asm/assembler.cpp
+++ b/asm/assembler.cpp
@@ -15,7 +15,7 @@ bool registerOp(const std::string& mnemonic, FactoryFunction f)
return false;
}
- std::cout << "Registering mnemonic |" << mnemonic << "|." << std::endl;
+ //std::cout << "Registering mnemonic |" << mnemonic << "|." << std::endl;
ops[mnemonic] = f;
diff --git a/asm/chunk.h b/asm/chunk.h
index cf6efaa..43cf54e 100644
--- a/asm/chunk.h
+++ b/asm/chunk.h
@@ -22,6 +22,8 @@ struct AddressFeature
{
std::string label;
+ bool relativeAddressing{true};
+
std::vector<uint8_t> machine_code;
size_t addr_size;
size_t addr_offs; ///< offset inside code
diff --git a/asm/intel64/jmp.cpp b/asm/intel64/jmp.cpp
index 30ae546..3899cac 100644
--- a/asm/intel64/jmp.cpp
+++ b/asm/intel64/jmp.cpp
@@ -78,18 +78,18 @@ Op_jmp::Op_jmp(const std::string& name, AsmArgs& args, const OP_T& jmp8, const O
label = std::any_cast<AsmArgs::Label>(args[0]).name();
if (!jmp32.empty()) { // set machine_code
- machine_code = jmp32 + OP_T{size_t(4), uint8_t(0)};
+ machine_code = jmp32 + OP_T(size_t(4), uint8_t(0));
addr_size = 4;
addr_offs = jmp32.size();
if (!jmp8.empty()) { // also provide alternative
- alternative_code = jmp8 + OP_T{size_t(1), uint8_t(0)};
+ alternative_code = jmp8 + OP_T(size_t(1), uint8_t(0));
alternative_size = 1;
alternative_offs = jmp8.size();
}
}
if (machine_code.empty() && !jmp8.empty()) {
- machine_code = jmp8 + OP_T{size_t(1), uint8_t(0)};
+ machine_code = jmp8 + OP_T(size_t(1), uint8_t(0));
addr_size = 1;
addr_offs = jmp8.size();
}
diff --git a/asm/segment.cpp b/asm/segment.cpp
index 9fb7a52..a4544f2 100644
--- a/asm/segment.cpp
+++ b/asm/segment.cpp
@@ -2,6 +2,11 @@
#include "operators.h"
+#include <boost/endian/conversion.hpp>
+
+#include <iostream>
+#include <exception>
+
using namespace std::string_literals;
size_t Segment::getAddressOfLabel(const std::string& label)
@@ -16,9 +21,22 @@ size_t Segment::getAddressOfLabel(const std::string& label)
return address;
}
}
+ i++;
}
- throw std::runtime_error("Bad label: "s + label);
+ throw std::runtime_error("Error: Label |"s + label + "| not found."s);
+}
+
+size_t Segment::getAddressOfIndex(size_t index)
+{
+ if (index >= size())
+ throw std::runtime_error("Error: Index |"s + std::to_string(index) + "| not found."s);
+
+ size_t address{0};
+ for (size_t i = 0; i < index; i++) {
+ address += (*this)[i]->size();
+ }
+ return address;
}
std::vector<uint8_t> Segment::getCode()
@@ -33,9 +51,34 @@ std::vector<uint8_t> Segment::getCode()
void Segment::insertAddresses()
{
+ // insert relative addresses
+ for (size_t i = 0; i < this->size(); i++) {
+ try {
+ AddressFeature& af { dynamic_cast<AddressFeature&>(*((*this)[i]))};
+
+ if (af.relativeAddressing == false)
+ throw std::runtime_error("Error: Absolute Addressing not supported.");
+
+ int64_t target_address = getAddressOfLabel(af.label); // throws if label not found
+ int64_t start_address = getAddressOfIndex(i); // throws if out of range
+ int64_t diff = target_address - start_address;
+ uint64_t udiff = static_cast<uint64_t>(diff);
+ if (af.addr_size == 1) {
+ if (diff < -128 || diff > 127)
+ throw std::runtime_error("Error: Address too far."s);
+ af.machine_code[af.addr_offs] = static_cast<uint8_t>(udiff);
+ } else if (af.addr_size == 4) {
+ *(reinterpret_cast<uint32_t*>(af.machine_code.data() + af.addr_offs)) = boost::endian::native_to_little(static_cast<uint32_t>(udiff));
+ } else
+ throw std::runtime_error("Error: unexpected addr_size: "s + std::to_string(af.addr_size));
+ } catch (const std::bad_cast& ex) {
+ // ignore, expected for non-addressing chunks
+ }
+ }
}
void Segment::optimize()
{
// TODO
}
+
diff --git a/asm/segment.h b/asm/segment.h
index dfacd12..97e1670 100644
--- a/asm/segment.h
+++ b/asm/segment.h
@@ -11,6 +11,7 @@ class Segment: public std::vector<std::shared_ptr<Chunk>>
{
public:
size_t getAddressOfLabel(const std::string& label);
+ size_t getAddressOfIndex(size_t index);
std::vector<uint8_t> getCode();
void insertAddresses();
void optimize();
diff --git a/test-asm.cpp b/test-asm.cpp
index 256902c..efdeab9 100644
--- a/test-asm.cpp
+++ b/test-asm.cpp
@@ -93,12 +93,26 @@ TEST_F(AsmTest, Intel64_multiple) {
Segment segment;
segment.push_back(makeOp("nop"));
- AsmArgs args{{AsmArgs::Immediate8(5)}};
- segment.push_back(makeOp("int", args));
+ AsmArgs args0{{AsmArgs::Immediate8(5)}};
+ segment.push_back(makeOp("int", args0));
segment.push_back(makeOp("ret"));
segment.push_back(makeLabel("data1"));
+ segment.push_back(makeOp("ret"));
+ AsmArgs args1{{AsmArgs::Label("data1")}};
+ segment.push_back(makeOp("jmp", args1));
segment.push_back(makeData({1, 2, 3}));
- ASSERT_EQ(segment.size(), 5);
- ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({0x90, 0xCD, 0x05, 0xC3, 0x01, 0x02, 0x03}));
+ segment.insertAddresses();
+
+ ASSERT_EQ(segment.size(), 7);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>(
+ {
+ 0x90, // nop
+ 0xCD, 0x05, // int 5
+ 0xC3, // ret
+ // data1:
+ 0xC3, // ret
+ 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, // jmp data1
+ 0x01, 0x02, 0x03 // data
+ }));
}