diff options
| -rw-r--r-- | asm/assembler.cpp | 2 | ||||
| -rw-r--r-- | asm/chunk.h | 2 | ||||
| -rw-r--r-- | asm/intel64/jmp.cpp | 6 | ||||
| -rw-r--r-- | asm/segment.cpp | 45 | ||||
| -rw-r--r-- | asm/segment.h | 1 | ||||
| -rw-r--r-- | test-asm.cpp | 22 | 
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 +  }));  } | 
