public static (bool Valid, ulong Value, int NBits) Evaluate_Constant(string str, bool isCapitals = false) { // 1] test whether str has digits, if it has none it is not a constant if (!str.Any(char.IsDigit)) { return(false, 0, -1); } // 2] test whether str is a constant var v = Parse_Constant(str, isCapitals); if (v.Valid) { return(v); } // 3] check if str contains operators if (str.Contains('+') || str.Contains('-') || str.Contains('*') || str.Contains('/') || str.Contains("<<") || str.Contains(">>")) { // second: if str is not a constant, test whether evaluating it yields a ulong try { var t = CSharpScript.EvaluateAsync <ulong>(str); ulong value = t.Result; bool isNegative = false; return(true, value, AsmSourceTools.NBitsStorageNeeded(value, isNegative)); } catch (Exception) {} } // 4] don't know what it is but it is not likely to be an constant. return(false, 0, -1); }
/// <summary> /// Returns true if the provided line only contains a remark (and no labels or code, it may have white space) /// </summary> /// <param name="line"></param> /// <returns></returns> public static bool IsRemarkOnly(string line) { int nChars = line.Length; for (int i = 0; i < nChars; ++i) { char c = line[i]; if (AsmSourceTools.IsRemarkChar(c)) { return(true); } else { if (char.IsWhiteSpace(c)) { // OK } else { return(false); } } } // did not find a remark character; this line is not a remark. return(false); }
/// <summary>Return the begin and end of the keyword</summary> public static (int BeginPos, int EndPos) GetKeywordPos(int pos, string line) { //Debug.WriteLine(string.Format("INFO: getKeyword; pos={0}; line=\"{1}\"", pos, new string(line))); if ((pos < 0) || (pos >= line.Length)) { return(pos, pos); } // find the beginning of the keyword int beginPos = 0; for (int i1 = pos - 1; i1 >= 0; --i1) { char c = line[i1]; if (AsmSourceTools.IsSeparatorChar(c) || Char.IsControl(c) || AsmSourceTools.IsRemarkChar(c)) { beginPos = i1 + 1; break; } } // find the end of the keyword int endPos = line.Length; for (int i2 = pos; i2 < line.Length; ++i2) { char c = line[i2]; if (AsmSourceTools.IsSeparatorChar(c) || Char.IsControl(c) || AsmSourceTools.IsRemarkChar(c)) { endPos = i2; break; } } return(BeginPos : beginPos, EndPos : endPos); }
private static Tuple <bool, int, int> getLabelDefPos_Regular(string line) { int nChars = line.Length; int i = 0; // find the start of the first keyword for (; i < nChars; ++i) { char c = line[i]; if (AsmSourceTools.isRemarkChar(c)) { return(new Tuple <bool, int, int>(false, 0, 0)); } else if (char.IsWhiteSpace(c)) { // do nothing } else { break; } } if (i >= nChars) { return(new Tuple <bool, int, int>(false, 0, 0)); } int beginPos = i; // position i points to the start of the current keyword //AsmDudeToolsStatic.Output("getLabelEndPos: found first char of first keyword "+ line[i]+"."); for (; i < nChars; ++i) { char c = line[i]; if (c.Equals(':')) { if (i == 0) // we found an empty label { return(new Tuple <bool, int, int>(false, 0, 0)); } else { return(new Tuple <bool, int, int>(true, beginPos, i)); } } else if (AsmSourceTools.isRemarkChar(c)) { return(new Tuple <bool, int, int>(false, 0, 0)); } else if (AsmSourceTools.isSeparatorChar(c)) { // found another keyword: labels can only be the first keyword on a line break; } } return(new Tuple <bool, int, int>(false, 0, 0)); }
private static (bool Valid, int BeginPos, int EndPos) GetLabelDefPos_Regular(string line) { int nChars = line.Length; int i = 0; // find the start of the first keyword for (; i < nChars; ++i) { char c = line[i]; if (AsmSourceTools.IsRemarkChar(c)) { return(Valid : false, BeginPos : 0, EndPos : 0); } else if (char.IsWhiteSpace(c)) { // do nothing } else { break; } } if (i >= nChars) { return(Valid : false, BeginPos : 0, EndPos : 0); } int beginPos = i; // position i points to the start of the current keyword //AsmDudeToolsStatic.Output_INFO("getLabelEndPos: found first char of first keyword "+ line[i]+"."); for (; i < nChars; ++i) { char c = line[i]; if (c.Equals(':')) { if (i == 0) { // we found an empty label return(Valid : false, BeginPos : 0, EndPos : 0); } else { return(Valid : true, BeginPos : beginPos, EndPos : i); } } else if (AsmSourceTools.IsRemarkChar(c)) { return(Valid : false, BeginPos : 0, EndPos : 0); } else if (AsmSourceTools.IsSeparatorChar(c)) { // found another keyword: labels can only be the first keyword on a line break; } } return(Valid : false, BeginPos : 0, EndPos : 0); }
public static string getKeyword(int pos, string line) { var t = AsmSourceTools.getKeywordPos(pos, line); int beginPos = t.Item1; int endPos = t.Item2; string result = line.Substring(beginPos, endPos - beginPos); return(result); }
public static List <string> SplitIntoKeywordsList(string line) { List <string> keywords = new List <string>(); foreach ((int BeginPos, int Length, bool IsLabel)pos in AsmSourceTools.SplitIntoKeywordPos(line)) { keywords.Add(AsmSourceTools.Keyword(pos, line)); } return(keywords); }
public Operand(string token) { //TODO: properly handle optional elements {K}{Z} {AES}{ER} string token2 = token. Replace("{K0}", ""). Replace("{K1}", ""). Replace("{K2}", ""). Replace("{K3}", ""). Replace("{K4}", ""). Replace("{K5}", ""). Replace("{K6}", ""). Replace("{K7}", ""). Replace("{Z}", ""). Replace("{ER}", ""). Replace("{SAE}", ""). Replace("{1TO4}", ""). Replace("{1TO8}", ""). Replace("{1TO16}", ""); this._str = token; Tuple <bool, Rn, int> t0 = RegisterTools.toRn(token2); if (t0.Item1) { this._type = Ot.reg; this._rn = t0.Item2; this._nBits = t0.Item3; } else { Tuple <bool, ulong, int> t1 = AsmSourceTools.toConstant(token2); if (t1.Item1) { this._type = Ot.imm; this._imm = t1.Item2; this._nBits = t1.Item3; } else { Tuple <bool, Rn, Rn, int, long, int> t2 = AsmSourceTools.parseMemOperand(token2); if (t2.Item1) { this._type = Ot.mem; this._mem = new Tuple <Rn, Rn, int, long>(t2.Item2, t2.Item3, t2.Item4, t2.Item5); this._nBits = t2.Item6; } else { this._type = Ot.UNKNOWN; this._nBits = -1; } } } }
public static int GetRemarkCharPosition(string line) { for (int i = 0; i < line.Length; ++i) { if (AsmSourceTools.IsRemarkChar(line[i])) { return(i); } } return(-1); }
/// <summary>Get the first position of a remark character in the provided line; /// Valid is true if one such char is found.</summary> public static (bool Valid, int BeginPos, int EndPos) GetRemarkPos(string line) { int nChars = line.Length; for (int i = 0; i < nChars; ++i) { if (AsmSourceTools.IsRemarkChar(line[i])) { return(Valid : true, BeginPos : i, EndPos : nChars); } } return(Valid : false, BeginPos : nChars, EndPos : nChars); }
public static Tuple <bool, int, int> getRemarkPos(string line) { int nChars = line.Length; for (int i = 0; i < nChars; ++i) { if (AsmSourceTools.isRemarkChar(line[i])) { return(new Tuple <bool, int, int>(true, i, nChars)); } } return(new Tuple <bool, int, int>(false, nChars, nChars)); }
/// <summary> /// Determine whether the provided pos is in a remark in the provided line. /// </summary> /// <param name="triggerPoint"></param> /// <param name="lineStart"></param> /// <returns></returns> public static bool IsInRemark(int pos, string line) { // check if the line contains a remark character before the current point int nChars = line.Length; int startPos = (pos >= nChars) ? nChars - 1 : pos; for (int i = startPos; i >= 0; --i) { if (AsmSourceTools.IsRemarkChar(line[i])) { return(true); } } return(false); }
public static Flags Parse(string str, bool strIsCapitals) { Contract.Requires(str != null); switch (AsmSourceTools.ToCapitals(str, strIsCapitals)) { case "CF": return(Flags.CF); case "PF": return(Flags.PF); case "AF": return(Flags.AF); case "ZF": return(Flags.ZF); case "SF": return(Flags.SF); case "OF": return(Flags.OF); case "DF": return(Flags.DF); default: return(Flags.NONE); } }
public static (bool valid, ulong value, int nBits) Evaluate_Constant(string str, bool isCapitals = false) { Contract.Requires(str != null); // 1] test whether str has digits, if it has none it is not a constant if (!str.Any(char.IsDigit)) { return(valid : false, value : 0, nBits : -1); } // 2] test whether str is a constant (bool valid, ulong value, int nBits)v = Parse_Constant(str, isCapitals); if (v.valid) { return(v); } // 3] check if str contains operators if (str.Contains('+') || str.Contains('-') || str.Contains('*') || str.Contains('/') || str.Contains("<<") || str.Contains(">>")) { // second: if str is not a constant, test whether evaluating it yields a ulong try { System.Threading.Tasks.Task <ulong> t = CSharpScript.EvaluateAsync <ulong>(str); ulong value = t.Result; bool isNegative = false; return(valid : true, value : value, nBits : AsmSourceTools.NBitsStorageNeeded(value, isNegative)); } catch (Exception) { // Do nothing } } // 4] don't know what it is but it is not likely to be a constant. return(valid : false, value : 0, nBits : -1); }
/// <summary> Check if the provided string is a constant. Does not evaluate arithmetic in the string </summary> public static (bool Valid, ulong Value, int NBits) Parse_Constant(string str, bool isCapitals = false) { string token2; bool isHex = false; bool isBinary = false; bool isDecimal = false; bool isOctal = false; bool isNegative = false; //Console.WriteLine("AsmSourceTools:ToConstant token=" + token); if (!isCapitals) { str = str.ToUpper(); } str = str.Trim(); if (str.StartsWith("-")) { token2 = str; isDecimal = true; isNegative = true; } // note the special case of token 0h (zero hex) should not be confused with the prefix 0h; else if (str.EndsWith("H", StringComparison.Ordinal)) { token2 = str.Substring(0, str.Length - 1); isHex = true; } else if (str.StartsWith("0H", StringComparison.Ordinal) || str.StartsWith("0X", StringComparison.Ordinal) || str.StartsWith("$0", StringComparison.Ordinal)) { token2 = str.Substring(2); isHex = true; } else if (str.StartsWith("0O", StringComparison.Ordinal) || str.StartsWith("0Q", StringComparison.Ordinal)) { token2 = str.Substring(2); isOctal = true; } else if (str.EndsWith("Q", StringComparison.Ordinal) || str.EndsWith("O", StringComparison.Ordinal)) { token2 = str.Substring(0, str.Length - 1); isOctal = true; } else if (str.StartsWith("0D", StringComparison.Ordinal)) { token2 = str.Substring(2); isDecimal = true; } else if (str.EndsWith("D", StringComparison.Ordinal)) { token2 = str; isDecimal = true; } else if (str.StartsWith("0B", StringComparison.Ordinal) || str.StartsWith("0Y", StringComparison.Ordinal)) { token2 = str.Substring(2); isBinary = true; } else if (str.EndsWith("Y", StringComparison.Ordinal)) { token2 = str.Substring(0, str.Length - 1); isBinary = true; } else { // special case with trailing B: either this B is from a hex number of the Binary if (str.EndsWith("B", StringComparison.Ordinal)) { bool parsedSuccessfully_tmp = ulong.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var dummy); if (parsedSuccessfully_tmp) { isHex = true; token2 = str; } else { token2 = str.Substring(0, str.Length - 1); isBinary = true; } } else { // assume decimal token2 = str; isDecimal = true; } } ulong value = 0; bool parsedSuccessfully; if (isHex) { parsedSuccessfully = ulong.TryParse(token2, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value); } else if (isOctal) { try { value = Convert.ToUInt64(token2, 8); parsedSuccessfully = true; } catch { parsedSuccessfully = false; } } else if (isBinary) { try { value = Convert.ToUInt64(token2, 2); parsedSuccessfully = true; } catch { parsedSuccessfully = false; } } else if (isDecimal) { if (isNegative) { parsedSuccessfully = long.TryParse(token2, NumberStyles.Integer, CultureInfo.CurrentCulture, out long signedValue); value = (ulong)signedValue; //Console.WriteLine("AsmSourceTools:ToConstant token2=" + token2 + "; signed value = " + Convert.ToString(signedValue, 16) + "; unsigned value = " + string.Format("{0:X}", value)); } else { parsedSuccessfully = ulong.TryParse(token2, NumberStyles.Integer, CultureInfo.CurrentCulture, out value); if (!parsedSuccessfully) { parsedSuccessfully = ulong.TryParse(token2, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value); } } } else { // unreachable parsedSuccessfully = false; } int nBits = (parsedSuccessfully) ? AsmSourceTools.NBitsStorageNeeded(value, isNegative) : -1; return(Valid : parsedSuccessfully, Value : value, NBits : nBits); }
public static (bool Valid, ulong Value, int NBits) Evaluate_Constant_OLD(string str, bool IsCapitals = false) { //Console.WriteLine("INFO: Evaluate_Constant: str=" + str + ": length=" + str.Length); if (!IsCapitals) { str = str.ToUpper(); } Stack <ulong> vStack = new Stack <ulong>(); Stack <Op> opStack = new Stack <Op>(); opStack.Push(Op.OPENING); // Implicit opening parenthesis int pos = 0; int exprLength = str.Length; while (pos <= exprLength) { if (pos == exprLength) { Process_Closing_Parenthesis(vStack, opStack); pos++; } else { char c = str[pos]; if (Char.IsWhiteSpace(c)) { pos++; } else { switch (c) { case ')': Process_Closing_Parenthesis(vStack, opStack); pos++; break; case '(': Process_Opening_Parenthesis(vStack, opStack); pos++; break; case '+': if (!Process_Input_Operator(Op.PLUS, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '-': if (!Process_Input_Operator(Op.MINUS, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '*': if (!Process_Input_Operator(Op.TIMES, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '/': if (!Process_Input_Operator(Op.DIV, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '|': if (!Process_Input_Operator(Op.OR, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '&': if (!Process_Input_Operator(Op.AND, vStack, opStack)) { return(false, 0, -1); } pos++; break; case '<': if ((pos + 1 < exprLength) && (str[pos + 1] == '<')) { pos++; if (!Process_Input_Operator(Op.SHL, vStack, opStack)) { return(false, 0, -1); } pos++; } break; case '>': if ((pos + 1 < exprLength) && (str[pos + 1] == '>')) { pos++; if (!Process_Input_Operator(Op.SHR, vStack, opStack)) { return(false, 0, -1); } pos++; } break; default: var v = Process_Input_Number(str, pos, vStack); if (!v.Valid) { return(false, 0, -1); } pos = v.Pos; break; } } } } if (vStack.Count == 1) // Result remains on values stacks { ulong v = vStack.Pop(); return(true, v, AsmSourceTools.NBitsStorageNeeded(v, false)); } else { return(false, 0, -1); } }
public static Arch ParseArch(string str, bool strIsCapitals, bool warn) { Contract.Requires(str != null); string str2 = AsmSourceTools.ToCapitals(str, strIsCapitals).Replace("_", string.Empty); switch (str2) { case "NONE": return(Arch.ARCH_NONE); case "8086": return(Arch.ARCH_8086); case "186": return(Arch.ARCH_186); case "286": return(Arch.ARCH_286); case "386": return(Arch.ARCH_386); case "486": return(Arch.ARCH_486); case "PENT": return(Arch.ARCH_PENT); case "P6": return(Arch.ARCH_P6); case "MMX": return(Arch.ARCH_MMX); case "SSE": return(Arch.ARCH_SSE); case "SSE2": return(Arch.ARCH_SSE2); case "SSE3": return(Arch.ARCH_SSE3); case "SSSE3": return(Arch.ARCH_SSSE3); case "SSE41": return(Arch.ARCH_SSE4_1); case "SSE42": return(Arch.ARCH_SSE4_2); case "SSE4A": return(Arch.ARCH_SSE4A); case "SSE5": return(Arch.ARCH_SSE5); case "AVX": return(Arch.ARCH_AVX); case "AVX2": return(Arch.ARCH_AVX2); case "AVX512VL": return(Arch.ARCH_AVX512_VL); case "AVX512DQ": return(Arch.ARCH_AVX512_DQ); case "AVX512BW": return(Arch.ARCH_AVX512_BW); case "AVX512ER": return(Arch.ARCH_AVX512_ER); case "AVX512F": return(Arch.ARCH_AVX512_F); case "AVX512CD": return(Arch.ARCH_AVX512_CD); case "AVX512PF": return(Arch.ARCH_AVX512_PF); case "AVX512IFMA": return(Arch.ARCH_AVX512_IFMA); case "AVX512VBMI": return(Arch.ARCH_AVX512_VBMI); case "AVX512VPOPCNTDQ": return(Arch.ARCH_AVX512_VPOPCNTDQ); case "AVX5124VNNIW": return(Arch.ARCH_AVX512_4VNNIW); case "AVX5124FMAPS": return(Arch.ARCH_AVX512_4FMAPS); case "VBMI2": case "AVX512VBMI2": return(Arch.ARCH_AVX512_VBMI2); case "VNNI": case "AVX512VNNI": return(Arch.ARCH_AVX512_VNNI); case "BITALG": case "AVX512BITALG": return(Arch.ARCH_AVX512_BITALG); case "GFNI": case "AVX512GFNI": return(Arch.ARCH_AVX512_GFNI); case "VAES": case "AVX512VAES": return(Arch.ARCH_AVX512_VAES); case "VPCLMULQDQ": case "AVX512VPCLMULQDQ": return(Arch.ARCH_AVX512_VPCLMULQDQ); case "AVX512BF16": return(Arch.ARCH_AVX512_BF16); case "AVX512VP2INTERSECT": return(Arch.ARCH_AVX512_VP2INTERSECT); case "HLE": return(Arch.ARCH_HLE); case "BMI1": return(Arch.ARCH_BMI1); case "BMI2": return(Arch.ARCH_BMI2); case "FMA": return(Arch.ARCH_FMA); case "AES": return(Arch.ARCH_AES); case "TBM": return(Arch.ARCH_TBM); case "AMD": return(Arch.ARCH_AMD); case "3DNOW": return(Arch.ARCH_3DNOW); case "IA64": return(Arch.ARCH_IA64); case "CYRIX": return(Arch.ARCH_CYRIX); case "CYRIXM": return(Arch.ARCH_CYRIXM); case "INVPCID": return(Arch.ARCH_INVPCID); case "VMX": return(Arch.ARCH_VMX); case "ADX": return(Arch.ARCH_ADX); case "X64": return(Arch.ARCH_X64); case "PCLMULQDQ": return(Arch.ARCH_PCLMULQDQ); case "RDPID": return(Arch.ARCH_RDPID); case "RDRAND": return(Arch.ARCH_RDRAND); case "RDSEED": return(Arch.ARCH_RDSEED); case "XSAVEOPT": return(Arch.ARCH_XSAVEOPT); case "XSS": return(Arch.ARCH_XSAVEOPT); case "XSAVE": return(Arch.ARCH_XSAVEOPT); case "XSAVEC": return(Arch.ARCH_XSAVEOPT); case "FSGSBASE": return(Arch.ARCH_FSGSBASE); case "LZCNT": return(Arch.ARCH_LZCNT); case "F16C": return(Arch.ARCH_F16C); case "MPX": return(Arch.ARCH_MPX); case "SHA": return(Arch.ARCH_SHA); case "RTM": return(Arch.ARCH_RTM); case "PREFETCHWT1": return(Arch.ARCH_PREFETCHWT1); case "PRFCHW": return(Arch.ARCH_PRFCHW); case "SGX1": return(Arch.ARCH_SGX1); case "SGX2": return(Arch.ARCH_SGX2); case "SMX": return(Arch.ARCH_SMX); case "CLDEMOTE": return(Arch.ARCH_CLDEMOTE); case "MOVDIR64B": return(Arch.ARCH_MOVDIR64B); case "MOVDIRI": return(Arch.ARCH_MOVDIRI); case "PCONFIG": return(Arch.ARCH_PCONFIG); case "WAITPKG": return(Arch.ARCH_WAITPKG); case "ENQCMD": return(Arch.ARCH_ENQCMD); case "UNDOC": return(Arch.ARCH_UNDOC); default: if (warn) { Console.WriteLine("WARNING: parseArch: no arch for str " + str); } return(Arch.ARCH_NONE); } }
/// <summary> /// return Offset = Base + (Index * Scale) + Displacement /// </summary> public static (bool valid, Rn baseReg, Rn indexReg, int scale, long displacement, int nBits) ParseMemOperand(string token) { int length = token.Length; if (length < 3) { return(valid : false, baseReg : Rn.NOREG, indexReg : Rn.NOREG, scale : 0, displacement : 0, nBits : 0); } // 1] select everything between [] int beginPos = length; for (int i = 0; i < length; ++i) { if (token[i] == '[') { beginPos = i + 1; } } int nBits = GetNbitsMemOperand(token); int endPos = length; for (int i = beginPos; i < length; ++i) { if (token[i] == ']') { endPos = i; } } token = token.Substring(beginPos, endPos - beginPos).Trim(); length = token.Length; if (length == 0) { return(valid : false, baseReg : Rn.NOREG, indexReg : Rn.NOREG, scale : 0, displacement : 0, nBits : 0); } // 2] check if the displacement is negative bool negativeDisplacement = token.Contains('-'); if (negativeDisplacement) { token = token.Replace('-', '+'); } // 3] remove superfluous initial + if (token[0] == '+') { token = token.Substring(1, length - 1).Trim(); } // 4] split based on + string[] x = token.Split('+'); Rn baseRn = Rn.NOREG; Rn indexRn = Rn.NOREG; int scale = 0; long displacement = 0; bool foundDisplacement = false; for (int i = 0; i < x.Length; ++i) { string y = x[i].Trim(); var t2 = AsmSourceTools.ToConstant(y); if (t2.valid) { if (foundDisplacement) { // found an second displacement, error return(valid : false, baseReg : Rn.NOREG, indexReg : Rn.NOREG, scale : 0, displacement : 0, nBits : 0); } else { foundDisplacement = true; displacement = (negativeDisplacement) ? -(long)t2.value : (long)t2.value; } } else { Rn t1 = RegisterTools.ParseRn(y); if (t1 != Rn.NOREG) { if (baseRn == Rn.NOREG) { baseRn = t1; } else { indexRn = t1; scale = 1; } } if (y.Contains('*')) { string[] z = y.Split('*'); string z0 = z[0].Trim(); string z1 = z[1].Trim(); Rn z0r = RegisterTools.ParseRn(z0); if (z0r != Rn.NOREG) { indexRn = z0r; scale = ParseScale(z1); } else { Rn z1r = RegisterTools.ParseRn(z1); if (z1r != Rn.NOREG) { indexRn = z1r; scale = ParseScale(z0); } } } } } if (scale == -1) { return(valid : false, baseReg : Rn.NOREG, indexReg : Rn.NOREG, scale : 0, displacement : 0, nBits : 0); } if ((baseRn != Rn.NOREG) && (indexRn != Rn.NOREG)) { if (RegisterTools.NBits(baseRn) != RegisterTools.NBits(indexRn)) { return(valid : false, baseReg : Rn.NOREG, indexReg : Rn.NOREG, scale : 0, displacement : 0, nBits : 0); } } return(valid : true, baseReg : baseRn, indexReg : indexRn, scale : scale, displacement : displacement, nBits : nBits); }
public static string GetKeyword(int pos, string line) { (int beginPos, int endPos) = AsmSourceTools.GetKeywordPos(pos, line); return(line.Substring(beginPos, endPos - beginPos)); }