├── .gitignore ├── include └── assembler.hpp ├── .editorconfig ├── makefile ├── src ├── main.cpp └── assembler.cpp ├── LICENSE.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | -------------------------------------------------------------------------------- /include/assembler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _ASSEMBLER_HPP 2 | #define _ASSEMBLER_HPP 3 | 4 | #include 5 | #include 6 | 7 | std::map assembler(std::vector const& assembly); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | 8 | [*.{c,h,cc,hh,cpp,hpp}] 9 | indent_style = space 10 | indent_size = 2 11 | trim_trailing_whitespace = true 12 | 13 | [{makefile,**.mk}] 14 | indent_style = tab 15 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # Directory Structure 2 | DIR_BIN = bin 3 | DIR_INC = include 4 | DIR_OBJ = obj 5 | DIR_SRC = src 6 | 7 | # Compiler Options 8 | CC = g++ 9 | CFLAGS = -Wall -iquote $(DIR_INC) -g 10 | BINARY = main 11 | 12 | # Make Options 13 | .PHONY: default main 14 | default: main 15 | 16 | # Main Command 17 | main: $(DIR_SRC)/main.cpp $(DIR_SRC)/assembler.cpp $(DIR_INC)/assembler.hpp 18 | $(CC) $(DIR_SRC)/main.cpp $(DIR_SRC)/assembler.cpp -o $(DIR_BIN)/$(BINARY) $(CFLAGS) 19 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "assembler.hpp" 7 | using namespace std; 8 | 9 | void print_result(vector instructions) 10 | { 11 | map programme = assembler(instructions); 12 | 13 | for (auto i = programme.begin(); i != programme.end(); ++i) 14 | { 15 | cout << i->first << ": " << i->second << endl; 16 | } 17 | cout << endl; 18 | } 19 | 20 | int main(void) 21 | { 22 | // Basic 23 | print_result({ "mov a 5", "inc a", ";spanner", "dec a", "dec a", "jnz a -1", "inc a" }); 24 | print_result({ "mov a -10", "mov b a", "inc a", "dec b", "jnz a -2" }); 25 | print_result({ "mov d 100", "dec d", "mov b d", "jnz b -2", "inc d", "mov a d", "jnz 5 10", "mov c a" }); 26 | 27 | // Arithmetic 28 | print_result( 29 | { 30 | "mov a -10", 31 | "mov b a", 32 | "add b 10", 33 | "inc a", 34 | "dec b", 35 | "jnz a -2", 36 | "mul b -2", 37 | "inc a", 38 | "dec b", 39 | "jnz b -2" 40 | }); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Chris MacBain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/assembler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "assembler.hpp" 8 | 9 | static std::vector split(std::string const& str) 10 | { 11 | std::string token; 12 | std::vector result; 13 | std::istringstream iss(str, std::istringstream::in); 14 | 15 | while (iss >> token) result.push_back(token); 16 | 17 | return result; 18 | } 19 | 20 | std::map assembler(std::vector const& assembly) 21 | { 22 | std::map registers; 23 | 24 | auto get_val = [&](std::string ins) -> int 25 | { 26 | return isalpha(ins[0]) ? registers[ins] : std::stoi(ins); 27 | }; 28 | for (unsigned i = 0; i < assembly.size(); i++) 29 | { 30 | std::vector instruction = split(assembly[i]); 31 | 32 | if (instruction[0][0] == ';') continue; 33 | 34 | if (instruction[0] == "mov") registers[instruction[1]] = get_val(instruction[2]); 35 | if (instruction[0] == "inc") registers[instruction[1]]++; 36 | if (instruction[0] == "dec") registers[instruction[1]]--; 37 | 38 | if (instruction[0] == "add") registers[instruction[1]] += get_val(instruction[2]); 39 | if (instruction[0] == "sub") registers[instruction[1]] -= get_val(instruction[2]); 40 | if (instruction[0] == "mul") registers[instruction[1]] *= get_val(instruction[2]); 41 | if (instruction[0] == "div") registers[instruction[1]] /= get_val(instruction[2]); 42 | 43 | if (instruction[0] == "jnz" && get_val(instruction[1])) i += get_val(instruction[2]) - 1; 44 | } 45 | return registers; 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple Assembler [![License](https://img.shields.io/github/license/Chris-1101/boxecho.svg)](https://github.com/Chris-1101/boxecho/blob/master/LICENSE.md) 2 | A personal project via which I aim to learn a bit about assembly by programming an interpretive implementation of select opcode mnemonics. 3 | 4 | ### Implemented Instructions 5 | * ✔ `MOV x, y` Move the contents of register `y` into register `x` (`x = y`) 6 | * ✔ `INC x` Increment register `x` by one (`x++`) 7 | * ✔ `DEC x` Decrement register `x` by one (`x--`) 8 | * ✔ `ADD x, y` Add the contents of register `y` to `x` (`x += y`) 9 | * ✔ `SUB x, y` Subtract the contents of register `y` from `x` (`x -= y`) 10 | * ✔ `MUL x, y` Multiply the contents of register `x` and `y`, store result in `x` (`x *= y`) 11 | * ✔ `DIV x, y` Integer divide the contents of register `x` by `y`, store result in `x` (`x /= y`) 12 | 13 | 14 | * ✔ `JNZ x, y` Jump `y` instructions if register `x` is Not Zero 15 | * ✔ `;` Comment, ignored by the interpreter 16 | 17 | ### Planned Instructions 18 | * ✘ `label:` Define a position within the code reachable by the `label` identifier 19 | * ✘ `call lbl` Procedure call to the subroutine identified by the label `lbl` 20 | * ✘ `ret` Return to the instruction that called the current subroutine 21 | 22 | 23 | * ✘ `CMP x, y` Compare the contents of registers `x` and `y` (result used by other instructions) 24 | * ✘ `JNE lbl` Jump to the label `lbl` if the values of the previous `CMP` were Not Equal 25 | * ✘ `JE lbl` Jump to the label `lbl` if the values of the previous `CMP` were Equal 26 | * ✘ `JGE lbl` Jump to the label `lbl` if register `x` was Greater than or Equal to `y` in the previous `CMP` 27 | * ✘ `JG lbl` Jump to the label `lbl` if register `x` was Greater than `y` in the previous `CMP` 28 | * ✘ `JLE lbl` Jump to the label `lbl` if register `x` was Lesser than or Equal to `y` in the previous `CMP` 29 | * ✘ `JL lbl` Jump to the label `lbl` if register `x` was Lesser than `y` in the previous `CMP` 30 | 31 | ### Further Instructions 32 | Reference: [Intel 80x86 ASM Opcodes](http://www.mathemainzel.info/files/x86asmref.html) 33 | --------------------------------------------------------------------------------