Advertisement
dark-s0ul

masm

Mar 14th, 2018
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 23.38 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2.  
  3. using namespace std;
  4.  
  5. #include <iostream>
  6. #include <fstream>
  7. #include <cstdarg>
  8. #include <string>
  9. #include <vector>
  10. #include <map>
  11.  
  12. bool isquote(char c)
  13. {
  14.     return (c == '"') || (c == '\'');
  15. }
  16.  
  17. bool issymbol(char c)
  18. {
  19.     return (c == '*') || (c == ':') || (c == ',') || (c == '[') || (c == ']');
  20. }
  21.  
  22. std::string format(const char *fmt, ...)
  23. {
  24.     va_list ap;
  25.     va_start(ap, fmt);
  26.  
  27.     char tmp[1024];
  28.     vsprintf(tmp, fmt, ap);
  29.     va_end(ap);
  30.  
  31.     return tmp;
  32. }
  33.  
  34. enum TType
  35. {
  36.     Undefined   = 0,
  37.     SingleChar  = 1 << 0,
  38.     String      = 1 << 1,
  39.     Binary      = 1 << 2,
  40.     Heximal     = 1 << 3,
  41.     Decimal     = 1 << 4,
  42.     Identifier  = 1 << 5,
  43.     DataType    = 1 << 6,
  44.     Directive   = 1 << 7,
  45.     Register8   = 1 << 8,
  46.     Register16  = 1 << 9,
  47.     Register32  = 1 << 10,
  48.     SRegister   = 1 << 11,
  49.     Instruction = 1 << 12,
  50.     PtrType     = 1 << 13,
  51.     Operator    = 1 << 14
  52. };
  53.  
  54. struct Token
  55. {
  56.     int index, first, last;
  57.     string text, info;
  58.     TType type;
  59.  
  60.     Token() : Token("", Undefined, 0, 0, 0, "Undefined") {}
  61.     Token(const string &text, TType type, int index, int first, int last, const string &info) : text(text), type(type), index(index), first(first), info(info) {}
  62. };
  63.  
  64. struct Symbol
  65. {
  66.     string segment, value, type, text;
  67.  
  68.     Symbol() {}
  69.     Symbol(const string &segment, const string &value, const string &type)
  70.     {
  71.         this->segment = segment;
  72.         this->value = value;
  73.         this->type = type;
  74.         this->text = "";
  75.     }
  76. };
  77.  
  78. struct Info
  79. {
  80.     int index, count;
  81.     Info(int index, int count)
  82.     {
  83.         this->index = index;
  84.         this->count = count;
  85.     }
  86. };
  87.  
  88. struct Operand
  89. {
  90.     enum class Type
  91.     {
  92.         Undef, Reg, Mem, Imm, Text, Name
  93.     } type;
  94.  
  95.     vector<Token> tokens;
  96.     int first;
  97.  
  98.     int ptr, scale, imm, disp;
  99.     Token reg, base, index;
  100.     string sreg, name, text;
  101.     bool valid;
  102.  
  103.     Operand(const int &first, const vector<Token> &tokens) : first(first), type(Type::Undef), valid(true), tokens(tokens) {}
  104.  
  105.     bool parse()
  106.     {
  107.         ptr = scale = imm = disp = 0;
  108.         reg = base = index = Token();
  109.  
  110.         int i = 0, len = tokens.size();
  111.  
  112.         if ((i < len) && (tokens[i].type == PtrType))
  113.         {
  114.             string ptr = tokens[i++].text;
  115.  
  116.             if ((i < len) && (tokens[i].type == Operator))
  117.             {
  118.                 i++;
  119.                 if (ptr.compare("BYTE") == 0)
  120.                 {
  121.                     this->ptr = 1;
  122.                 }
  123.                 else if (ptr.compare("WORD") == 0)
  124.                 {
  125.                     this->ptr = 2;
  126.                 }
  127.                 else if (ptr.compare("DWORD") == 0)
  128.                 {
  129.                     this->ptr = 4;
  130.                 }
  131.                 else return false;
  132.             }
  133.             else return valid = false;
  134.             goto is_mem;
  135.         }
  136.  
  137.         if ((i < len) && ((tokens[i].type == Register8) || (tokens[i].type == Register32)))
  138.         {
  139.             type = Type::Reg;
  140.             this->reg = tokens[i++];
  141.             return valid = i == len;
  142.         }
  143.         else if ((i < len) && (tokens[i].type == Binary))
  144.         {
  145.             type = Type::Imm;
  146.             this->imm = stol(tokens[i++].text, 0, 2);
  147.             return valid = i == len;
  148.         }
  149.         else if ((i < len) && (tokens[i].type == Decimal))
  150.         {
  151.             type = Type::Imm;
  152.             this->imm = stol(tokens[i++].text, 0, 10);
  153.             return valid = i == len;
  154.         }
  155.         else if ((i < len) && (tokens[i].type == Heximal))
  156.         {
  157.             type = Type::Imm;
  158.             this->imm = stol(tokens[i++].text, 0, 16);
  159.             return valid = i == len;
  160.         }
  161.         else if ((i < len) && (tokens[i].type == String))
  162.         {
  163.             type = Type::Text;
  164.             this->text = tokens[i++].text;
  165.             return valid = i == len;
  166.         }
  167.  
  168.     is_mem:
  169.         if ((i < len) && (tokens[i].type == SRegister))
  170.         {
  171.             const Token &sreg = tokens[i++];
  172.             if ((i < len) && (tokens[i].text.compare(":") == 0))
  173.             {
  174.                 i++;
  175.                 this->sreg = sreg.text;
  176.             }
  177.             else return valid = i == len;
  178.         }
  179.  
  180.         if ((i < len) && (tokens[i].type == Identifier))
  181.         {
  182.             type = Type::Name;
  183.             this->name = tokens[i++].text;
  184.             if ((i < len) && (tokens[i].text.compare("[") == 0))
  185.             {
  186.                 type = Type::Mem;
  187.                 i++;
  188.                 if ((i < len) && (tokens[i].type == Register32))
  189.                 {
  190.                     this->base = tokens[i++];
  191.                     if ((i < len) && (tokens[i].text.compare("]"))) i++;
  192.                     return i == len;
  193.                 }
  194.                 else return valid = false;
  195.             }
  196.         }
  197.         else return valid = false;
  198.     }
  199.  
  200.     bool IsRegister()
  201.     {
  202.         return type == Type::Reg;
  203.     }
  204.  
  205.     bool IsMemory()
  206.     {
  207.         return type == Type::Mem;
  208.     }
  209.  
  210.     bool IsImmediate()
  211.     {
  212.         return type == Type::Imm;
  213.     }
  214.  
  215.     bool IsString()
  216.     {
  217.         return type == Type::Text;
  218.     }
  219.  
  220.     bool IsName()
  221.     {
  222.         return type == Type::Name;
  223.     }
  224. };
  225.  
  226. struct Sentence
  227. {
  228.     string prefix, bytes, source;
  229.     bool printable, skip, valid;
  230.     unsigned offset, length;
  231.  
  232.     Info label, name, mnemo;
  233.     vector<Operand> operands;
  234.     vector<Token> tokens;
  235.  
  236.     Sentence(const string &source, const vector<Token> tokens) : skip(false), valid(true), source(source), tokens(tokens), label(-1, 0), name(-1, 0), mnemo(-1, 0), printable(false), offset(0)
  237.     {
  238.         length = 0;
  239.         int len = tokens.size(), i = 0;
  240.  
  241.         if ((i < len) && (tokens[i].type == Identifier))
  242.         {
  243.             int index = i++;
  244.             if ((i < len) && (tokens[i].text.compare(":") == 0))
  245.             {
  246.                 this->label.index = index;
  247.                 i++;
  248.             }
  249.             else
  250.             {
  251.                 this->name.index = index;
  252.             }
  253.         }
  254.  
  255.         if ((i < len) && ((tokens[i].type == Directive) || (tokens[i].type == DataType) || (tokens[i].type == Instruction)))
  256.         {
  257.             this->mnemo.index = i++;
  258.         }
  259.  
  260.         while (i < len)
  261.         {
  262.             vector<Token> operand_tokens;
  263.             int index = i;
  264.             while (i < len)
  265.             {
  266.                 if (tokens[i].text.compare(",") == 0)
  267.                 {
  268.                     i++;
  269.                     break;
  270.                 }
  271.                 operand_tokens.push_back(tokens[i++]);
  272.             }
  273.             Operand operand(index, operand_tokens);
  274.             operand.parse();
  275.  
  276.             operands.push_back(operand);
  277.         }
  278.  
  279.         while (operands.size() < 2)
  280.         {
  281.             operands.push_back(Operand(-1, {}));
  282.         }
  283.     }
  284.  
  285.     bool lookup(struct Compiler *);
  286.     void writeSyntax(FILE *);
  287.     void writeOffset(FILE *);
  288. };
  289.  
  290. struct If { bool value; };
  291. struct Compiler
  292. {
  293.     map<string, vector<Token>> eques;
  294.     map<string, unsigned> segments;
  295.     map<string, Symbol> symbols;
  296.     vector<Sentence> sentences;
  297.     string filename, listing;
  298.     vector<If> ifTable;
  299.     bool lexicalError;
  300.     unsigned offset;
  301.     int lineNumber;
  302.     string segment;
  303.  
  304.     Compiler() : lexicalError(false) {}
  305.  
  306.     static bool IsDirective(const std::string & text);
  307.  
  308.     static bool IsDataType(const std::string & text);
  309.  
  310.     static bool IsPtrType(const std::string & text);
  311.  
  312.     static bool IsPtrOperator(const std::string & text);
  313.  
  314.     static bool IsRegister8Bit(const std::string & text);
  315.  
  316.     static bool IsRegister16Bit(const std::string & text);
  317.  
  318.     static bool IsRegister32Bit(const std::string & text);
  319.  
  320.     static bool IsSegmentRegister(const std::string & text);
  321.  
  322.     static bool IsInstruction(const std::string & text);
  323.  
  324.     vector<Token> tokenize(string &);
  325.     void parse(int argc, char *argv[]);
  326.     void write();
  327.  
  328.     bool SetEqu(const string &text, const vector<Token> &tokens)
  329.     {
  330.         if (eques.find(text) != eques.end()) return false;
  331.         eques[text] = tokens;
  332.         return true;
  333.     }
  334.     bool AddSymbol(const string &text, const Symbol &symbol)
  335.     {
  336.         if (symbols.find(text) != symbols.end()) return false;
  337.         symbols[text] = symbol;
  338.         return true;
  339.     }
  340.  
  341.     bool firstSegment(const string &text)
  342.     {
  343.         offset = 0;
  344.         if (!segment.empty()) return false;
  345.         segment = text;
  346.         return true;
  347.     }
  348.  
  349.     bool EndSegment(const string &text, const int &length)
  350.     {
  351.         if (segment.empty() || (segment.compare(text) != 0)) return false;
  352.         segments[text] = length;
  353.         segment.clear();
  354.         return true;
  355.     }
  356. };
  357.  
  358. bool Compiler::IsDirective(const std::string & text)
  359. {
  360.     return !text.compare("END")
  361.         || !text.compare("SEGMENT")
  362.         || !text.compare("ENDS")
  363.         || !text.compare("MACRO")
  364.         || !text.compare("ENDM")
  365.         || !text.compare("ELSE")
  366.         || !text.compare("ENDIF");
  367. }
  368.  
  369. bool Compiler::IsDataType(const std::string & text)
  370. {
  371.     return !text.compare("DB")
  372.         || !text.compare("DW")
  373.         || !text.compare("DD");
  374. }
  375.  
  376. bool Compiler::IsPtrType(const std::string & text)
  377. {
  378.     return !text.compare("BYTE")
  379.         || !text.compare("WORD")
  380.         || !text.compare("DWORD");
  381. }
  382.  
  383. bool Compiler::IsPtrOperator(const std::string & text)
  384. {
  385.     return !text.compare("PTR");
  386. }
  387.  
  388. bool Compiler::IsRegister8Bit(const std::string & text)
  389. {
  390.     return !text.compare("AH")
  391.         || !text.compare("BH")
  392.         || !text.compare("CH")
  393.         || !text.compare("DH")
  394.         || !text.compare("AL")
  395.         || !text.compare("BL")
  396.         || !text.compare("CL")
  397.         || !text.compare("DL");
  398. }
  399.  
  400. bool Compiler::IsRegister16Bit(const std::string & text)
  401. {
  402.     return !text.compare("AX")
  403.         || !text.compare("BX")
  404.         || !text.compare("CX")
  405.         || !text.compare("DX")
  406.         || !text.compare("SI")
  407.         || !text.compare("DI")
  408.         || !text.compare("SP")
  409.         || !text.compare("BP");
  410. }
  411.  
  412. bool Compiler::IsRegister32Bit(const std::string & text)
  413. {
  414.     return !text.compare("EAX")
  415.         || !text.compare("EBX")
  416.         || !text.compare("ECX")
  417.         || !text.compare("EDX")
  418.         || !text.compare("ESI")
  419.         || !text.compare("EDI")
  420.         || !text.compare("ESP")
  421.         || !text.compare("EBP");
  422. }
  423.  
  424. bool Compiler::IsSegmentRegister(const std::string & text)
  425. {
  426.     return !text.compare("CS")
  427.         || !text.compare("DS")
  428.         || !text.compare("SS")
  429.         || !text.compare("ES")
  430.         || !text.compare("ES")
  431.         || !text.compare("FS")
  432.         || !text.compare("GS");
  433. }
  434.  
  435. bool Compiler::IsInstruction(const std::string & text)
  436. {
  437.     return
  438.         !text.compare("CWDE") ||
  439.         !text.compare("INC") ||
  440.         !text.compare("STOS") ||
  441.         !text.compare("ADD") ||
  442.         !text.compare("CMP") ||
  443.         !text.compare("AND") ||
  444.         !text.compare("MOV") ||
  445.         !text.compare("OR") ||
  446.         !text.compare("JBE");
  447. }
  448.  
  449. vector<Token> Compiler::tokenize(string &source)
  450. {
  451.     vector<Token> tokens;
  452.     int len = source.size(), index = 0, i = 0;
  453.     while (i < len)
  454.     {
  455.         if (isspace(source[i])) i++;
  456.         else if (isalpha(source[i]))
  457.         {
  458.             Token token;
  459.             token.first = i;
  460.             token.index = index++;
  461.             while ((i < len) && isalnum(source[i]))
  462.             {
  463.                 token.text += toupper(source[i++]);
  464.             }
  465.             token.last = i;
  466.            
  467.             [&token](const string &text)
  468.             {
  469.                 if (IsDirective(text))
  470.                 {
  471.                     token.type = Directive;
  472.                     token.info = "Directive";
  473.                 }
  474.                 else if (IsDataType(text))
  475.                 {
  476.                     token.type = DataType;
  477.                     token.info = "Data type";
  478.                 }
  479.                 else if (IsPtrType(text))
  480.                 {
  481.                     token.type = PtrType;
  482.                     token.info = "Ptr type";
  483.                 }
  484.                 else if (IsPtrOperator(text))
  485.                 {
  486.                     token.type = Operator;
  487.                     token.info = "Ptr operator";
  488.                 }
  489.                 else if (IsRegister8Bit(text))
  490.                 {
  491.                     token.type = Register8;
  492.                     token.info = "8-bit register";
  493.                 }
  494.                 else if (IsRegister16Bit(text))
  495.                 {
  496.                     token.type = Register16;
  497.                     token.info = "16-bit register";
  498.                 }
  499.                 else if (IsRegister32Bit(text))
  500.                 {
  501.                     token.type = Register32;
  502.                     token.info = "32-bit register";
  503.                 }
  504.                 else if (IsSegmentRegister(text))
  505.                 {
  506.                     token.type = SRegister;
  507.                     token.info = "Segment register";
  508.                 }
  509.                 else if (IsInstruction(text))
  510.                 {
  511.                     token.type = Instruction;
  512.                     token.info = "Instruction";
  513.                 }
  514.                 else
  515.                 {
  516.                     token.type = Identifier;
  517.                     token.info = "Identifier";
  518.                 }
  519.             }(token.text);
  520.  
  521.             if (token.type == Identifier)
  522.             {
  523.                 const auto &equ = eques.find(token.text);
  524.                 if (equ != eques.end())
  525.                 {
  526.                     source = source.replace(token.first, token.text.size(), symbols[token.text].text);
  527.                     for (Token token : equ->second)
  528.                     {
  529.                         token.index = index++;
  530.                         tokens.push_back(token);
  531.                     }
  532.                 }
  533.                 else tokens.push_back(token);
  534.             }
  535.             else tokens.push_back(token);
  536.         }
  537.         else if (isdigit(source[i]))
  538.         {
  539.             Token token;
  540.             token.first = i;
  541.             token.index = index++;
  542.             token.type = Decimal;
  543.             while ((i < len) && isalnum(source[i]))
  544.             {
  545.                 token.text += source[i++];
  546.             }
  547.             token.last = i;
  548.             char c = token.text.back();
  549.             if (toupper(c) == 'B')
  550.             {
  551.                 token.type = Binary;
  552.                 token.info = "Binary";
  553.                 auto pos = token.text.find_first_not_of("01");
  554.                 // lexicalError = (pos != string::npos) && (pos != (token.text.size() - 1));
  555.             }
  556.             else if (toupper(c) == 'H')
  557.             {
  558.                 token.type = Heximal;
  559.                 token.info = "Heximal";
  560.                 auto pos = token.text.find_first_not_of("0123456789ABCDEF");
  561.                 // lexicalError = (pos != string::npos) && (pos != (token.text.size() - 1));
  562.             }
  563.             else
  564.             {
  565.                 token.type = Decimal;
  566.                 token.info = "Decimal";
  567.                 auto pos = token.text.find_first_not_of("0123456789");
  568.                 // lexicalError = (pos != string::npos) && (pos != (token.text.size() - 1));
  569.             }
  570.             tokens.push_back(token);
  571.         }
  572.         else if ((source[i] == '"') || (source[i] == '\''))
  573.         {
  574.             char quote = source[i++];
  575.             int first = i;
  576.             string text;
  577.             while ((i < len) && (source[i] != '\n') && (source[i] != quote))
  578.             {
  579.                 text += source[i++];
  580.             }
  581.             int last = i++;
  582.             tokens.push_back(Token(text, String, index++, first, last, "String"));
  583.             // lexicalError = (source[i++] != quote);
  584.         }
  585.         else
  586.         {
  587.             int first = i;
  588.             bool symbol = (source[i] == '[') || (source[i] == ']') || (source[i] == ':') || (source[i] == ',');
  589.             // lexicalError = !((source[i] == '[') || (source[i] == ']') || (source[i] == ':') || (source[i] == ','));
  590.             int last = ++i;
  591.             tokens.push_back(Token(string(1, source[first]), symbol ? SingleChar : Undefined, index++, first, last, symbol ? "Single char" : "Undefined"));
  592.         }
  593.     }
  594.     return tokens;
  595. }
  596.  
  597. int SizeOfImm(int type, int imm)
  598. {
  599.     if (type == 1)
  600.     {
  601.         if ((-256 <= imm) && (imm < 256)) return 1;
  602.         else return -1;
  603.     }
  604.     else if (type == 2)
  605.     {
  606.         if ((-65536 <= imm) && (imm < 65536))
  607.         {
  608.             return ((-128 <= imm) && (imm < 128)) ? 1 : 2;
  609.         }
  610.         else return -1;
  611.     }
  612.     return ((-128 <= imm) && (imm < 128)) ? 1 : 4;
  613. }
  614.  
  615. int SizeOfDisp(int disp)
  616. {
  617.     return ((0x80 <= disp) && (disp < 0xFF80) || (0x10000 <= disp) && (disp < 0xFFFF80) || (0x1000000 <= disp) && (disp < 0xFFFFFF80)) ? 4 : 1;
  618. }
  619.  
  620. string GetSegmentOfReg(const Token &reg)
  621. {
  622.     string text = reg.text;
  623.     if ((text.compare("ESP") == 0) || (text.compare("EBP") == 0) || (text.compare("SP") == 0) || (text.compare("BP") == 0)) return "SS";
  624.     else if (reg.type == Register32) return "DS";
  625.     else return "";
  626. }
  627.  
  628. bool Sentence::lookup(Compiler *view)
  629. {
  630.     int len = tokens.size();
  631.  
  632.     if (label.index != -1)
  633.     {
  634.         if (!view->AddSymbol(tokens[label.index].text, Symbol(view->segment, format(" %.4X ", view->offset), "L NEAR")))
  635.         {
  636.             return valid = false;
  637.         }
  638.         printable = true;
  639.     }
  640.     else if (mnemo.index != -1)
  641.     {
  642.         auto &mnemocode = tokens[mnemo.index];
  643.         if (name.index != -1)
  644.         {
  645.             if (mnemocode.text.compare("SEGMENT") == 0)
  646.             {
  647.                 if (!view->firstSegment(tokens[name.index].text)) return valid = false;
  648.                 printable = true;
  649.             }
  650.             else if (mnemocode.text.compare("ENDS") == 0)
  651.             {
  652.                 if (!view->EndSegment(tokens[name.index].text, view->offset)) return valid = false;
  653.                 printable = true;
  654.             }
  655.             else if (mnemocode.text.compare("EQU") == 0)
  656.             {
  657.                 vector<Token> equ;
  658.                 int i = mnemo.index + 1;
  659.                 if (i < len)
  660.                 {
  661.                     while (i < len)
  662.                     {
  663.                         equ.push_back(tokens[i++]);
  664.                     }
  665.                 }
  666.                 else return false;
  667.                 int count = equ.size();
  668.  
  669.                 Symbol symbol;
  670.                 symbol.text = source.substr(equ[0].first, equ[count - 1].last);
  671.                 if (count == 1)
  672.                 {
  673.                     symbol.type = "NUMBER";
  674.                     if (equ[0].type == Binary)
  675.                     {
  676.                         symbol.value = format("%.4X", stol(symbol.text, 0, 2));
  677.                     }
  678.                     else if (equ[0].type == Heximal)
  679.                     {
  680.                         symbol.value = format("%.4X", stol(symbol.text, 0, 10));
  681.                     }
  682.                     else if (equ[0].type == Decimal)
  683.                     {
  684.                         symbol.value = format("%.4X", stol(symbol.text, 0, 16));
  685.                     }
  686.                     else return valid = false;
  687.                     prefix = format(" = %s ", symbol.value.c_str());
  688.                 }
  689.                 else if (count > 0)
  690.                 {
  691.                     symbol.type = "TEXT";
  692.                     symbol.value = symbol.text;
  693.                     prefix = " =     ";
  694.                 }
  695.                 else return valid = false;
  696.                 if (!view->AddSymbol(tokens[name.index].text, symbol)) return valid = false;
  697.                 if (!view->SetEqu(tokens[name.index].text, equ)) return valid = false;
  698.             }
  699.             else if (mnemocode.type == DataType)
  700.             {
  701.                 Symbol symbol;
  702.                 symbol.value = format(" %.4X ", view->offset);
  703.                 symbol.segment = view->segment;
  704.  
  705.                 if (mnemocode.text.compare("DB") == 0)
  706.                 {
  707.                     symbol.type = "L BYTE";
  708.                     if (operands[0].valid)
  709.                     {
  710.  
  711.                         if (operands[0].IsString())
  712.                         {
  713.                             length = operands[0].text.size();
  714.                         }
  715.                         else if (operands[0].IsImmediate())
  716.                         {
  717.                             length = 1;
  718.                         }
  719.                         else return valid = false;
  720.                     }
  721.                     else return valid = false;
  722.                 }
  723.                 else if (mnemocode.text.compare("DW") == 0)
  724.                 {
  725.                     symbol.type = "L WORD";
  726.                     if (operands[0].valid)
  727.                     {
  728.                         if (operands[0].IsImmediate())
  729.                         {
  730.                             length = 2;
  731.                         }
  732.                         else return valid = false;
  733.                     }
  734.                     else return valid = false;
  735.                 }
  736.                 else if (mnemocode.text.compare("DD") == 0)
  737.                 {
  738.                     symbol.type = "L DWORD";
  739.                     if (operands[0].valid)
  740.                     {
  741.                         if (operands[0].IsImmediate())
  742.                         {
  743.                             length = 4;
  744.                         }
  745.                         else return valid = false;
  746.                     }
  747.                     else return valid = false;
  748.                 }
  749.  
  750.                 if (!view->AddSymbol(tokens[name.index].text, symbol))
  751.                 {
  752.                     return valid = false;
  753.                 }
  754.                 printable = true;
  755.             }
  756.         }
  757.         else if (mnemocode.text.compare("IF") == 0)
  758.         {
  759.             if (operands[0].IsImmediate())
  760.             {
  761.                 If context;
  762.                 context.value = operands[0].imm;
  763.                 skip = !context.value;
  764.                 view->ifTable.push_back(context);
  765.             }
  766.             else return valid = false;
  767.         }
  768.         else if (mnemocode.text.compare("ELSE") == 0)
  769.         {
  770.             if (view->ifTable.empty()) return valid = false;
  771.             If &context = view->ifTable.back();
  772.             skip = !(context.value = !context.value);
  773.         }
  774.         else if (mnemocode.text.compare("ENDIF") == 0)
  775.         {
  776.             if (view->ifTable.empty()) return valid = false;
  777.             view->ifTable.pop_back();
  778.         }
  779.         else if (!view->ifTable.empty() && !view->ifTable.back().value)
  780.         {
  781.             skip = true;
  782.         }
  783.         else if (mnemocode.text.compare("END") == 0)
  784.         {
  785.  
  786.         }
  787.         else if (mnemocode.type == Instruction)
  788.         {
  789.             printable = true;
  790.  
  791.             if (mnemocode.text.compare("CWDE") == 0)
  792.             {
  793.                 length = 2;
  794.             }
  795.             else if (mnemocode.text.compare("INC") == 0)
  796.             {
  797.                 if (!operands[0].IsRegister()) return valid = false;
  798.                 length = 1;
  799.             }
  800.             else if (mnemocode.text.compare("STOS") == 0)
  801.             {
  802.                 if (operands[0].IsMemory())
  803.                 {
  804.                     Token &base = operands[0].base;
  805.                     string &sreg = operands[0].sreg;
  806.  
  807.                     length = 1/*instr*/ + 1/*mod*/ + 4/*ident*/;
  808.  
  809.                     if (!sreg.empty() && (sreg.compare(GetSegmentOfReg(base)) || sreg.compare("DS"))) length += 1;
  810.                 }
  811.                 else return valid = false;
  812.             }
  813.             else if (mnemocode.text.compare("ADD") == 0)
  814.             {
  815.                 if (operands[0].IsRegister() && operands[1].IsRegister())
  816.                 {
  817.                     if (operands[0].reg.type == operands[1].reg.type) length = 2;
  818.                     else return valid = false;
  819.                 }
  820.                 else return valid = false;
  821.             }
  822.             else if (mnemocode.text.compare("CMP") == 0)
  823.             {
  824.                 if (operands[0].IsRegister() && operands[1].IsMemory())
  825.                 {
  826.                     const Token &reg = operands[0].reg;
  827.                     Token &base = operands[1].base;
  828.                     string &sreg = operands[1].sreg;
  829.  
  830.                     length = 1/*instr*/ + 1/*mod*/ + 4/*ident*/;
  831.  
  832.                     if (!sreg.empty() && (sreg.compare(GetSegmentOfReg(base)) || sreg.compare("DS"))) length += 1;
  833.                 }
  834.                 else return valid = false;
  835.             }
  836.             else if (mnemocode.text.compare("AND") == 0)
  837.             {
  838.                 if (operands[0].IsMemory() && operands[1].IsRegister())
  839.                 {
  840.                     Token &base = operands[0].base;
  841.                     string &sreg = operands[0].sreg;
  842.  
  843.                     length = 1/*instr*/ + 1/*mod*/ + 4/*ident*/;
  844.  
  845.                     if (!sreg.empty() && (sreg.compare(GetSegmentOfReg(base)) || sreg.compare("DS"))) length += 1;
  846.                 }
  847.                 else return valid = false;
  848.             }
  849.             else if (mnemocode.text.compare("MOV") == 0)
  850.             {
  851.                 if (operands[0].IsRegister() && operands[1].IsImmediate())
  852.                 {
  853.                     length = 1 + SizeOfImm(operands[0].tokens[0].type == Register8 ? 1 : 4, operands[1].imm & 0xFFFFFFFF);
  854.                 }
  855.                 else return valid = false;
  856.             }
  857.             else if (mnemocode.text.compare("OR") == 0)
  858.             {
  859.                 if (operands[0].IsMemory() && operands[1].IsImmediate())
  860.                 {
  861.                     length = 1/*instr*/ + 1/*mod*/ + 4/*ident*/ + SizeOfImm(operands[0].ptr, operands[1].imm & 0xFFFFFFFF);
  862.                 }
  863.                 else return valid = false;
  864.             }
  865.             else if (mnemocode.text.compare("JBE") == 0)
  866.             {
  867.                 if (operands[0].IsMemory())
  868.                 {
  869.                     Token &base = operands[0].base;
  870.                     string &sreg = operands[0].sreg;
  871.  
  872.                     length = 1/*instr*/ + 1/*mod*/ + 4/*ident*/;
  873.  
  874.                     if (!sreg.empty() && (sreg.compare(GetSegmentOfReg(base)) || sreg.compare("DS"))) length += 1;
  875.                 }
  876.                 else if (operands[0].IsName())
  877.                 {
  878.                     string &sreg = operands[0].sreg;
  879.  
  880.                     length = (view->symbols.find(operands[0].name) != view->symbols.end()) ? 2 : 6;
  881.  
  882.                     if (!sreg.empty() && sreg.compare("DS")) length += 1;
  883.                 }
  884.                 else return valid = false;
  885.             }
  886.         }
  887.     }
  888.     else if ((name.index != -1) || !operands.empty())
  889.     {
  890.         return valid = false;
  891.     }
  892.     return true;
  893. }
  894.  
  895. void Sentence::writeSyntax(FILE *file)
  896. {
  897.     if (source.empty()) return;
  898.     fprintf(file, " Label  Mnemocode  1st operand  2nd operand\n");
  899.     fprintf(file, " index    index    index count  index count\n");
  900.  
  901.     fprintf(file, " %5i  %9i  %5i %5i  %5i %5i\n\n", label.index & name.index, mnemo.index, operands[0].first, operands[0].tokens.size(), operands[1].first, operands[1].tokens.size());
  902.     int index = 0;
  903.     for (auto &token : tokens)
  904.     {
  905.         fprintf(file, "%-2d | %11s | %2i | %16s |\n", index++, token.text.c_str(), token.text.size(), token.info.c_str());
  906.     }
  907.     fprintf(file, "\n");
  908. }
  909.  
  910. void Sentence::writeOffset(FILE *file)
  911. {
  912.     if (skip == false)
  913.     {
  914.         if (printable) fprintf(file, " %.4X ", offset);
  915.         else if (prefix.empty()) fprintf(file, "    ");
  916.         else fprintf(file, prefix.c_str());
  917.  
  918.         fprintf(file, "\t\t%s\n", source.c_str());
  919.     }
  920. }
  921.  
  922. void Compiler::parse(int argc, char *argv[])
  923. {
  924.     if (argc > 1) filename = argv[1];
  925.     auto pos = filename.find_last_of(".");
  926.     cout << "Source filename[.asm]: " << filename;
  927.     if (argc <= 1) while (!getline(cin, filename)); else cout << endl;
  928.     if (filename.find_last_of(".") == string::npos) filename += ".asm";
  929.  
  930.     if (argc > 2) listing = argv[2];
  931.     cout << "Source listing[.lst]: " << listing;
  932.     if (argc <= 2) getline(cin, listing); else cout << endl;
  933.     if (listing.find_last_of(".") == string::npos) listing += ".lst";
  934.     cout << endl;
  935.  
  936.     ifTable.clear();
  937.  
  938.     lineNumber = 0;
  939.     string line;
  940.     ifstream file(filename);
  941.     offset = 0;
  942.     while (getline(file, line))
  943.     {
  944.         lexicalError = false;
  945.         lineNumber++;
  946.         const auto &tokens = tokenize(line);
  947.         Sentence sentence(line, tokens);
  948.         sentence.lookup(this);
  949.         sentence.offset = offset;
  950.         offset += sentence.length;
  951.         sentences.push_back(sentence);
  952.     }
  953.     file.close();
  954. }
  955.  
  956. void Compiler::write()
  957. {
  958.     if (FILE *file = fopen((filename.substr(0, filename.find_last_of(".")) + ".lex").c_str(), "w"))
  959.     {
  960.         int lineNumber = 0;
  961.         for (auto &sentence : sentences)
  962.         {
  963.             fprintf(file, " %s\n", sentence.source.c_str());
  964.             sentence.writeSyntax(file);
  965.             lineNumber++;
  966.         }
  967.         fclose(file);
  968.     }
  969.  
  970.     if (FILE *file = fopen(listing.c_str(), "w"))
  971.     {
  972.         int lineNumber = 0;
  973.         for (auto &sentence : sentences)
  974.         {
  975.             sentence.writeOffset(file);
  976.             lineNumber++;
  977.         }
  978.  
  979.         fprintf(file, "\n\n                N a m e          Size    Length\n\n");
  980.         for (auto &segment : segments)
  981.         {
  982.             fprintf(file, "%-32s\t%-7s\t%-.4X\n", segment.first.c_str(), "32 Bit", segment.second);
  983.         }
  984.  
  985.         fprintf(file, "\nSymbols:\n                N a m e          Type     Value   Attr\n");
  986.         for (auto symbol : symbols)
  987.         {
  988.             fprintf(file, "%-32s\t%-7s\t%-s\t%s\n", symbol.first.c_str(), symbol.second.type.c_str(), symbol.second.value.c_str(), symbol.second.segment.c_str());
  989.         }
  990.         fprintf(file, "\n");
  991.         fclose(file);
  992.     }
  993. }
  994.  
  995. int main(int argc, char *argv[])
  996. {
  997.     Compiler compiler;
  998.     compiler.parse(argc, argv);
  999.     compiler.write();
  1000. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement