private static void CountModRm(TableCurrInstruct CurrInstr) { if (CurrInstr.Name == "MOV") { if (TableOperand.GetByNumbers(1, true).MainAttr != 0) { CurrInstr.IncByteCount(1, TableCurrInstruct.Types.модрм); } else if (TableOperand.TypeSecond == TableOperand.Types.Адресний_вираз) { CurrInstr.IncByteCount(1, TableCurrInstruct.Types.модрм); } return; } if (CurrInstr.Name == "JMP") { if (TableOperand.GetByNumbers(4, true).IsLexemePresent)//визначений ідентифікатор { TableUser.Types userType = TableUser.GetByNumber(TableOperand.GetByNumbers(4, true).MainAttr).Type; if (userType != TableUser.Types.Far) { CurrInstr.IncByteCount(1, TableCurrInstruct.Types.модрм); } } return; } if (TableInstruction.GetByName(CurrInstr.Name).ModRM) { CurrInstr.IncByteCount(1, TableCurrInstruct.Types.модрм); } }
private static string CreateOffset(TableCurrInstruct CurrInstr) { string Offset = ""; int UserNumber = 0; if (TableOperand.TypeFirst >= TableOperand.Types.Мітка && TableOperand.TypeFirst <= TableOperand.Types.Адресний_вираз) { UserNumber = TableOperand.GetByNumbers(4, true).MainAttr; } if (TableOperand.TypeSecond >= TableOperand.Types.Мітка && TableOperand.TypeSecond <= TableOperand.Types.Адресний_вираз) { UserNumber = TableOperand.GetByNumbers(4, false).MainAttr; } if (UserNumber > 0) { Offset = Convert.ToString(TableUser.GetByNumber(UserNumber).Offset, 16); Offset = CheckCharCount(Offset, 8); if (CurrInstr.Name == "JMP" && !CurrInstr.IsModRm) { Offset += " ----"; } } return(Offset.ToUpper()); }
private static string CreateNumber(int ByteCount) { string result = ""; long Number = TableOperand.GetByNumbers(10, true).MainAttr; try { switch (ByteCount) { case 2: result = Convert.ToString(Convert.ToByte(Number), 16).ToUpper(); break; case 4: result = Convert.ToString(Convert.ToInt16(Number), 16).ToUpper(); break; case 8: result = Convert.ToString(Convert.ToInt32(Number), 16).ToUpper(); break; default: break; } result = CheckCharCount(result, ByteCount); } catch { Errors.Add(2);//@error number too big } return(result); }
private static int DoOpConst() {//количество байт, выделенных под данные int byteCount = TableInstruction.GetByName(TableLexeme.MnemName()).ByteCount; int result = byteCount; int value; if (TableSentence.Item.Operands[1, 0] != 0) // есть второй операнд { Errors.Add(20); //@error слишком много операндов } if (TableSentence.Item.Operands[0, 1] == 1) //константа { TableLexeme lex = TableLexeme.GetByNumber(TableSentence.Item.Operands[0, 0]); //первая лексема первого операнда value = lex.NumberDex(); double f = Math.Pow(2, 8 * byteCount) - 1; uint j = Convert.ToUInt32(f); if (value > j) { Errors.Add(2);//@error too big number } TableOperand.GetByNumbers(10, isFirst).Modify(value, byteCount); } else//выражение { int FirstLex = TableSentence.Item.Operands[0, 0]; int LastLex = FirstLex + TableSentence.Item.Operands[0, 1] - 1; int Const = Calc.DoCalc(FirstLex, LastLex); result = LastLex - FirstLex; TableOperand.GetByNumbers(10, isFirst).Modify(Const, byteCount); } AnalysisGrammar.AddTableUser(byteCount); return(result); }
private static void ClearTables() { if (TableAsmWords.Items.Count == 0)//создаем раз и навсегда { TableAsmWords.Create(); } if (TableRegister.Items.Count == 0) { TableRegister.Create(); } if (TableInstruction.Items.Count == 0) { TableInstruction.Create(); } if (TableOperand.ItemsFirst.Count == 0 && TableOperand.ItemsSecond.Count == 0) { TableOperand.Create(); } if (TableAssume.Item.Count == 0) { new TableAssume(); } if (Errors.Templates.Count == 0) { Errors.CreateTempl(); } Errors.Table.Clear(); Errors.Items.Clear(); Result.Items.Clear(); Result.Table.Clear(); TableSegment.Items.Clear(); TableSegment.Table.Clear(); TableUser.Items.Clear(); TableUser.Table.Clear(); }
private static void DoOpSeg(TableLexeme Lexeme) { TableLexeme LexemeNext = TableLexeme.GetByNumber(Lexeme.Number + 1); if (LexemeNext.Type != TableAsmWords.Types.мітка && LexemeNext.Type != TableAsmWords.Types.користувач) { Errors.Add(10);//@error неправильный агрумент у Seg } TableOperand.GetByNumbers(9, isFirst).Modify(LexemeNext.Number, -1); }
private static string CreateModRm() { string Mod = ""; string Reg = ""; string Rm = ""; switch (TableSentence.Item.Mnem) { case "CMP": Reg = Convert.ToString(TableOperand.GetByNumbers(1, false).MainAttr, 2); //второй регистр Reg = CheckCharCount(Reg, 3); //есть сиб и смещение : нет сиба, есть смещение Mod = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? "10" : "00"; Rm = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? "100" : "101"; break; case "JMP": Reg = "101"; //кусок команды //есть сиб и смещение : нет сиба, есть смещение Mod = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? "10" : "00"; Rm = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? "100" : "101"; break; case "MOV": Reg = Convert.ToString(TableOperand.GetByNumbers(1, true).MainAttr, 2); //первый регистр Reg = CheckCharCount(Reg, 3); //есть сиб и смещение : нет сиба, есть смещение Mod = TableOperand.TypeSecond == TableOperand.Types.Адресний_вираз ? "10" : "00"; Rm = TableOperand.TypeSecond == TableOperand.Types.Адресний_вираз ? "100" : "101"; break; case "NEG": Reg = "011"; //кусок команды Mod = "11"; //операнд - всегда регистр Rm = Convert.ToString(TableOperand.GetByNumbers(1, true).MainAttr, 2); //первый регистр Rm = CheckCharCount(Rm, 3); break; case "PUSH": Reg = "110"; //кусок команды Mod = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? "10" : "00"; Rm = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? "100" : "101"; break; default: break; } int ModRmDex = Convert.ToInt32(Mod + Reg + Rm, 2); string ModRm = Convert.ToString(ModRmDex, 16).ToUpper(); ModRm = CheckCharCount(ModRm, 2); return(ModRm); }
private static string CreateSib() { string Sib = ""; //строка результата bool isFirst = TableOperand.TypeFirst == TableOperand.Types.Адресний_вираз ? true : false; //первый ли операнд switch (TableOperand.GetByNumbers(8, isFirst).ExtraAttr) {//кусочек ss case 1: Sib += "00"; break; case 2: Sib += "01"; break; case 4: Sib += "10"; break; case 8: Sib += "11"; break; default: break; } int scaledReg = TableOperand.GetByNumbers(8, isFirst).MainAttr; string Index = Convert.ToString(scaledReg, 2); Index = CheckCharCount(Index, 3); Sib += Index; int unScaledReg; if (TableOperand.GetByNumbers(6, isFirst).MainAttr == scaledReg) { unScaledReg = TableOperand.GetByNumbers(7, isFirst).MainAttr; } else { unScaledReg = TableOperand.GetByNumbers(6, isFirst).MainAttr; } string Base = Convert.ToString(unScaledReg, 2); Base = CheckCharCount(Base, 3); Sib += Base; //двоичный код int SibDex = Convert.ToInt16(Sib, 2); //десятичный код Sib = Convert.ToString(SibDex, 16); //16 код return(Sib.ToUpper()); }
private static int CountData() { switch (TableOperand.TypeFirst) { case TableOperand.Types.Константа: return(TableOperand.GetByNumbers(10, true).ExtraAttr); case TableOperand.Types.Текст: return(TableOperand.GetByNumbers(11, true).MainAttr); default: return(1); } }
private static void DoOpText() { TableLexeme lex = TableLexeme.GetByNumber(TableSentence.Item.Operands[0, 0]);//первая лексема первого операнда int byteCount = TableInstruction.GetByName(TableLexeme.MnemName()).ByteCount; if (byteCount == 1) { byteCount *= lex.Length; } else { Errors.Add(14);//@error недопустимий аргумент директиви } TableOperand.GetByNumbers(11, isFirst).Modify(byteCount, -1); AnalysisGrammar.AddTableUser(1); }
private static int DoOpSymbols(TableLexeme Lexeme) { switch (Lexeme.Name) { case "[": isAdress = true; break; case "]": isAdress = false; break; case "*": int EndOfConst = Lexeme.Number; while (TableLexeme.GetByNumber(EndOfConst + 1).Name != "]") { EndOfConst++; } int RegNumber; if (TableOperand.GetByNumbers(7, isFirst).IsLexemePresent) { RegNumber = TableOperand.GetByNumbers(7, isFirst).MainAttr; } else { RegNumber = TableOperand.GetByNumbers(6, isFirst).MainAttr; } int ConstValue = Calc.DoCalc(Lexeme.Number + 1, EndOfConst); if (ConstValue == 1 || ConstValue == 2 || ConstValue == 4 || ConstValue == 8) { TableOperand.GetByNumbers(8, isFirst).Modify(RegNumber, ConstValue); } else { Errors.Add(9); //@error wrong multiplier } return(EndOfConst - Lexeme.Number); //прыгаем в конец конст. выражения default: break; } return(0); }
private static void CountPrefix(TableCurrInstruct CurrInstr) { if (CurrInstr.Name != "PUSH" && CurrInstr.Name != "CMP" && CurrInstr.Name != "MOV" && CurrInstr.Name != "JMP") { return;//префикса быть не может } bool isFirstOp = CurrInstr.Name == "MOV" ? false : true; int DefaultRegisterNum = 3;//ds int MultipliedRegister = TableOperand.GetByNumbers(8, isFirstOp).MainAttr; int FirstAdressRegister = TableOperand.GetByNumbers(6, isFirstOp).MainAttr; int SecondAdressRegister = TableOperand.GetByNumbers(7, isFirstOp).MainAttr; if (MultipliedRegister != 4 && MultipliedRegister != 5) //множитель не при ebp esp { if (FirstAdressRegister == 4 || FirstAdressRegister == 5 || //ebp или esp есть SecondAdressRegister == 4 || SecondAdressRegister == 5) { DefaultRegisterNum = 2;//ss } } if (TableOperand.GetByNumbers(3, isFirstOp).IsLexemePresent) { int PrefReg = TableOperand.GetByNumbers(3, isFirstOp).MainAttr; if (PrefReg != DefaultRegisterNum) { CurrInstr.IncByteCount(1, TableCurrInstruct.Types.префікс); //префикс задан явно и не совпадает по умолчанию } } else //префикс не задан явно if (TableOperand.GetByNumbers(4, isFirstOp).IsLexemePresent) //є ідентиф користувача { int userNumber = TableOperand.GetByNumbers(4, isFirstOp).MainAttr; //номер рядка в таблиці користувача string logicSegment = TableUser.GetByNumber(userNumber).ActiveSeg; //ім'я логічного сегменту string userRegister = TableAssume.GetByName(logicSegment); //имя регистра логического сегмента var Register = TableRegister.GetByName(userRegister); //сам регистр if (Register != null && Register.Number != DefaultRegisterNum) { CurrInstr.IncByteCount(1, TableCurrInstruct.Types.префікс); //нужно генерировать незаданный префикс } } }
private static void DoOpRegister(TableLexeme Lexeme) { int RegNum = TableRegister.GetByName(Lexeme.Name).Number; if (isAdress) { if (!TableOperand.GetByNumbers(6, isFirst).IsLexemePresent) { TableOperand.GetByNumbers(6, isFirst).Modify(RegNum, 32); } else { TableOperand.GetByNumbers(7, isFirst).Modify(RegNum, 32); } } else { TableOperand.GetByNumbers(1, isFirst).Modify(RegNum, 32); } }
private static void DoOpName(TableLexeme Lexeme) { TableUser user = TableUser.GetByName(Lexeme.Name); if (user != null) { TableOperand.GetByNumbers(4, isFirst).Modify(user.Number, -1); } else { TableOperand.GetByNumbers(5, isFirst).Modify(-1, -1); } if (TableLexeme.MnemName() == "DD") { AnalysisGrammar.AddTableUser(4); } else { AnalysisGrammar.AddTableUser(-1); } }
private static string CreatePrefix(TableCurrInstruct CurrInstr) { bool isFirstOp = CurrInstr.Name == "MOV" ? false : true; int DefaultRegisterNum = 3;//ds int MultipliedRegister = TableOperand.GetByNumbers(8, isFirstOp).MainAttr; int FirstAdressRegister = TableOperand.GetByNumbers(6, isFirstOp).MainAttr; int SecondAdressRegister = TableOperand.GetByNumbers(7, isFirstOp).MainAttr; if (MultipliedRegister != 4 && MultipliedRegister != 5) //множитель не при ebp esp { if (FirstAdressRegister == 4 || FirstAdressRegister == 5 || //ebp или esp есть SecondAdressRegister == 4 || SecondAdressRegister == 5) { DefaultRegisterNum = 2;//ss } } string Prefix = ""; TableOperand OperPref = TableOperand.GetByNumbers(3, isFirstOp); if (OperPref.IsLexemePresent) //задан явно == не совпадает по умолчанию { Prefix = TableRegister.GetByNumbers(OperPref.MainAttr, 2).PrefixString; //нужный префикс // CurrInstr.Prefix = Prefix; } else //префикс не задан явно { int userNumber = TableOperand.GetByNumbers(4, isFirstOp).MainAttr;//номер рядка в таблиці користувача string logicSegment = TableUser.GetByNumber(userNumber).ActiveSeg; //ім'я логічного сегменту string userRegister = TableAssume.GetByName(logicSegment); //имя регистра логического сегмента var Register = TableRegister.GetByName(userRegister); //сам регистр if (Register != null && Register.Number != DefaultRegisterNum) //нужно генерировать незаданный префикс { Prefix = Register.PrefixString; // CurrInstr.Prefix = Prefix; } } return(Prefix); }
private static void DoOpType(TableLexeme Lexeme) { switch (Lexeme.Name) { case "DWORD": if (!TableOperand.GetByNumbers(2, isFirst).IsLexemePresent) { TableOperand.GetByNumbers(2, isFirst).Modify(4, -1); } break; case "FWORD": if (!TableOperand.GetByNumbers(2, isFirst).IsLexemePresent) { TableOperand.GetByNumbers(2, isFirst).Modify(6, -1); } break; case "FAR": if (!TableOperand.GetByNumbers(2, isFirst).IsLexemePresent) { TableOperand.GetByNumbers(2, isFirst).Modify(5, -1); } break; case "PTR": if (!TableOperand.GetByNumbers(2, isFirst).IsLexemePresent) { Errors.Add(8); //@error type is missing } break; default: Errors.Add(5); //@error какая-то хрень break; } }
public static void DoOperands()//обробка операндів { string mnemName = TableSentence.Item.Mnem; int opCount; if (TableInstruction.GetByName(mnemName) != null)//у директиви або інструкції є операнди { opCount = TableInstruction.GetByName(mnemName).OperandCount; } else//інші директиви { opCount = 0; } if (mnemName != "ASSUME" && opCount != TableSentence.Item.OpCount) { Errors.Add(6);//@error Невірна кількість операндів } else { for (int i = 0; i < TableSentence.Item.OpCount; i++)//для каждого операнда { isFirst = (i == 0) ? true : false; int j = 0; while (j < TableSentence.Item.Operands[i, 1]) { TableLexeme Lexeme = TableLexeme.GetByNumber(TableSentence.Item.Operands[i, 0] + j); switch (Lexeme.Type) { case TableAsmWords.Types.регістр: DoOpRegister(Lexeme); break; case TableAsmWords.Types.сегментний_регістр: DoOpSegRegister(Lexeme); break; case TableAsmWords.Types.тип: DoOpType(Lexeme); break; case TableAsmWords.Types.користувач: DoOpName(Lexeme); break; case TableAsmWords.Types.символ: j += DoOpSymbols(Lexeme); break; case TableAsmWords.Types.seg: DoOpSeg(Lexeme); break; case TableAsmWords.Types.число: j += DoOpConst(); break; case TableAsmWords.Types.текст: DoOpText(); break; default: break; } j++; } TableOperand.IdentifyOperands(isFirst); } } bool result = opCount > 0 ? TableOperand.VerifyOperands(mnemName) : true; if (!result) { Errors.Add(15);//@error Помилкові операнди } }
private static void DoOpSegRegister(TableLexeme Lexeme) { int RegNum = TableRegister.GetByName(Lexeme.Name).Number; TableOperand.GetByNumbers(3, isFirst).Modify(RegNum, -1); }
public static void FormSentenceTable() { Mnem = ""; NameOrLabelNumber = 0; MnemNumber = 0; Type = TableAsmWords.Types.пусто; for (int k = 0; k < 6; k++) { for (int l = 0; l < 2; l++) { Operands[k, l] = 0; } } TableSentence.Item = null; //Обнуляем таблицу предложения в начале строки TableSentence.Table.Clear(); TableOperand.ReCreate(); //Обнуляем таблицы операндов в начале строки foreach (var lexem in TableLexeme.Items) { if (lexem.AsmWord() != null) { if ((lexem.Type == TableAsmWords.Types.інструкція) || (lexem.Type == TableAsmWords.Types.директива)) { MnemNumber = lexem.Number; Mnem = lexem.Name; if (MnemNumber > 1)//mnem not first { NameOrLabelNumber = 1; } Type = lexem.Type; } } } switch (MnemNumber) { case 0: //label only possible if (TableLexeme.Items[0].Type == TableAsmWords.Types.користувач && TableLexeme.Items[1].Name == ":") //it IS label { NameOrLabelNumber = 1; Mnem = TableLexeme.Items[0].Name; Type = TableAsmWords.Types.мітка; } else { Errors.Add(5); //@error хз шо не удалось определить конструкцию } IsComa = false; break; case 1: //команда IsComa = true; break; case 2: //директива if (TableLexeme.Items[0].Type == TableAsmWords.Types.користувач) //имя на своём месте { IsComa = true; } else { Errors.Add(5); //@error хз шо не удалось определить конструкцию } break; case 3: //команда с меткой в одной строке if (TableLexeme.Items[0].Type == TableAsmWords.Types.користувач && TableLexeme.Items[1].Name == ":") //there IS label { IsComa = true; } else { Errors.Add(5); //@error хз шо не удалось определить конструкцию } break; default: Errors.Add(5); //@error хз шо не удалось определить конструкцию break; } if (MnemNumber < TableLexeme.Count && Mnem != "LABEL" && IsComa)//mnem has operands { ReadOperands(); } new TableSentence(Mnem, NameOrLabelNumber, MnemNumber, Operands, Type); }