assemble
This commit is contained in:
parent
680e952d04
commit
19f68cc6ac
@ -51,7 +51,7 @@ key_press_int:
|
||||
|
||||
mov r0, [0x600]
|
||||
add r0, r0, VCD
|
||||
mov r1, [KBC_CODE]
|
||||
mov r1, [KBD_CODE]
|
||||
cmp r1, 44 ; spacebar
|
||||
mov r2, rfl
|
||||
and r2, r2, FL_EQ
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
#include <print>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@ -100,7 +101,7 @@ auto Assembler::assemble_file()
|
||||
}
|
||||
|
||||
assert(value->ty == EOT::Imm);
|
||||
m_syms[stmt->ident] = value->as_imm();
|
||||
m_syms[std::string(stmt->ident)] = value->as_imm();
|
||||
|
||||
} else if (parser.next_is_align()) {
|
||||
auto stmt = parser.parse_align();
|
||||
@ -153,6 +154,11 @@ auto Assembler::assemble_file()
|
||||
parser.try_recover();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line->labels) {
|
||||
define_labels(*line->labels);
|
||||
}
|
||||
|
||||
lines.push_back(std::move(line));
|
||||
}
|
||||
}
|
||||
@ -165,33 +171,36 @@ auto Assembler::assemble_file()
|
||||
m_second_pass = true;
|
||||
|
||||
for (const auto& line : lines) {
|
||||
std::println("[{}] = {}", m_builder.ip(), line->ident);
|
||||
assemble_line(*line);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 64; i += 4) {
|
||||
std::println("{:02x} {:02x} {:02x} {:02x}",
|
||||
m_program[i],
|
||||
m_program[i + 1],
|
||||
m_program[i + 2],
|
||||
m_program[i + 3]);
|
||||
}
|
||||
|
||||
return std::move(m_program);
|
||||
}
|
||||
|
||||
void Assembler::assemble_define_labels(const std::vector<Label>& labels)
|
||||
void Assembler::define_labels(const std::vector<Label>& labels)
|
||||
{
|
||||
for (const auto& label : labels) {
|
||||
if (label.is_local) {
|
||||
m_sublabels[label.ident] = m_builder.ip();
|
||||
m_sublabels[label_ident(label)] = m_builder.ip();
|
||||
} else {
|
||||
m_sublabels.clear();
|
||||
m_syms[label.ident] = m_builder.ip();
|
||||
m_superlabel = label.ident;
|
||||
m_syms[std::string(label.ident)] = m_builder.ip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Assembler::label_ident(const Label& label) const -> std::string
|
||||
{
|
||||
if (not label.is_local)
|
||||
return std::string(label.ident);
|
||||
|
||||
return sublabel_ident(label.ident);
|
||||
}
|
||||
auto Assembler::sublabel_ident(std::string_view ident) const -> std::string
|
||||
{
|
||||
return std::format("{}{}", m_superlabel, ident);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
enum class Mnemonic {
|
||||
@ -576,9 +585,9 @@ auto Assembler::eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>
|
||||
return std::make_unique<EO>(loc, EOT::Str, expr.as_str());
|
||||
case Expr::Ty::Mem:
|
||||
case Expr::Ty::MemWord:
|
||||
return eval_operand_mem(expr);
|
||||
return eval_operand_mem(*expr.as_unary());
|
||||
case Expr::Ty::MemByte: {
|
||||
auto evaled = eval_operand_mem(expr);
|
||||
auto evaled = eval_operand_mem(*expr.as_unary());
|
||||
switch (evaled->ty) {
|
||||
case EOT::MemWordImm:
|
||||
evaled->ty = EOT::MemByteImm;
|
||||
@ -587,7 +596,7 @@ auto Assembler::eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>
|
||||
evaled->ty = EOT::MemByteReg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
assert(false && "should be either of the above");
|
||||
}
|
||||
return evaled;
|
||||
}
|
||||
@ -631,7 +640,8 @@ auto Assembler::eval_operand_mem(const Expr& expr)
|
||||
expr.loc, EOT::MemWordImm, op->as_imm());
|
||||
}
|
||||
case Expr::Ty::Reg:
|
||||
return std::make_unique<EO>(expr.loc, EOT::Reg, expr.as_reg());
|
||||
return std::make_unique<EO>(
|
||||
expr.loc, EOT::MemWordReg, expr.as_reg());
|
||||
case Expr::Ty::Str:
|
||||
case Expr::Ty::Mem:
|
||||
case Expr::Ty::MemByte:
|
||||
@ -704,7 +714,8 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
||||
auto loc = expr.loc;
|
||||
switch (expr.ty) {
|
||||
case Expr::Ty::Ident: {
|
||||
if (!m_syms.contains(expr.as_ident())) {
|
||||
auto ident = std::string(expr.as_ident());
|
||||
if (!m_syms.contains(ident)) {
|
||||
if (m_second_pass) {
|
||||
error(expr.loc,
|
||||
std::format(
|
||||
@ -715,11 +726,12 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
||||
}
|
||||
}
|
||||
|
||||
auto value = m_syms[expr.as_ident()];
|
||||
auto value = m_syms[ident];
|
||||
return std::make_unique<EO>(loc, EOT::Imm, value);
|
||||
}
|
||||
case Expr::Ty::SubLabel: {
|
||||
if (!m_sublabels.contains(expr.as_ident())) {
|
||||
auto ident = sublabel_ident(expr.as_ident());
|
||||
if (!m_sublabels.contains(ident)) {
|
||||
if (m_second_pass) {
|
||||
error(expr.loc,
|
||||
std::format(
|
||||
@ -730,7 +742,7 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
||||
}
|
||||
}
|
||||
|
||||
auto value = m_sublabels[expr.as_ident()];
|
||||
auto value = m_sublabels[ident];
|
||||
return std::make_unique<EO>(loc, EOT::Imm, value);
|
||||
}
|
||||
case Expr::Ty::Reg:
|
||||
@ -908,7 +920,9 @@ auto Parser::parse_line() -> std::unique_ptr<Line>
|
||||
error(current_loc(), "expected identifier");
|
||||
return nullptr;
|
||||
}
|
||||
ident = m_tok.text;
|
||||
ident = is_local
|
||||
? std::string_view(m_tok.text.data() - 1, m_tok.text.size() + 1)
|
||||
: m_tok.text;
|
||||
step();
|
||||
|
||||
if (not eat(':')) {
|
||||
|
||||
@ -210,15 +210,18 @@ namespace asmer {
|
||||
auto assemble_file()
|
||||
-> std::expected<std::vector<uint8_t>, std::string>;
|
||||
|
||||
void assemble_define_labels(const std::vector<Label>& labels);
|
||||
void assemble_line(const Line& line);
|
||||
|
||||
auto ok() const -> bool
|
||||
{
|
||||
return not m_failed;
|
||||
}
|
||||
|
||||
private:
|
||||
void define_labels(const std::vector<Label>& labels);
|
||||
void assemble_line(const Line& line);
|
||||
|
||||
auto label_ident(const Label& label) const -> std::string;
|
||||
auto sublabel_ident(std::string_view ident) const -> std::string;
|
||||
|
||||
auto eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>;
|
||||
auto eval_operand_mem(const Expr& expr)
|
||||
-> std::unique_ptr<EvaledOperand>;
|
||||
@ -237,8 +240,9 @@ namespace asmer {
|
||||
std::string_view m_text;
|
||||
std::vector<uint8_t> m_program;
|
||||
Builder m_builder;
|
||||
std::unordered_map<std::string_view, uint16_t> m_syms {};
|
||||
std::unordered_map<std::string_view, uint16_t> m_sublabels {};
|
||||
std::unordered_map<std::string, uint16_t> m_syms {};
|
||||
std::string m_superlabel {};
|
||||
std::unordered_map<std::string, uint16_t> m_sublabels {};
|
||||
bool m_second_pass = false;
|
||||
bool m_failed = false;
|
||||
};
|
||||
|
||||
@ -53,7 +53,8 @@ private:
|
||||
class FileDisk final : public BlockDevice {
|
||||
public:
|
||||
explicit FileDisk(fs::path file_path)
|
||||
: m_file(file_path, std::ios_base::binary)
|
||||
: m_file(file_path,
|
||||
std::ios_base::binary | std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
if (not m_file) {
|
||||
throw std::invalid_argument(std::format(
|
||||
|
||||
23
src/main.cpp
23
src/main.cpp
@ -29,6 +29,29 @@ int main(int argc, char** argv)
|
||||
} else {
|
||||
auto disk = FileDisk(argv[1]);
|
||||
|
||||
auto memory_disk = MemoryDisk(128);
|
||||
make_program(memory_disk.data());
|
||||
|
||||
auto file_block = std::vector<uint8_t>(BlockDevice::block_size);
|
||||
disk.read(file_block.data(), 0);
|
||||
|
||||
auto memory_block = std::vector<uint8_t>(BlockDevice::block_size);
|
||||
memory_disk.read(memory_block.data(), 0);
|
||||
|
||||
std::println("file memory");
|
||||
for (size_t i = 0; i < 64; i += 4) {
|
||||
std::println(
|
||||
"{:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}",
|
||||
file_block[i],
|
||||
file_block[i + 1],
|
||||
file_block[i + 2],
|
||||
file_block[i + 3],
|
||||
memory_block[i],
|
||||
memory_block[i + 1],
|
||||
memory_block[i + 2],
|
||||
memory_block[i + 3]);
|
||||
}
|
||||
|
||||
auto vm = VM(*device, disk);
|
||||
vm.run();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user