Parse_Mem_Operand(string token, bool isCapitals = false) { int length = token.Length; if (length < 3) { return(Valid : false, BaseReg : Rn.NOREG, IndexReg : Rn.NOREG, Scale : 0, Displacement : 0, NBits : 0, ErrorMessage : null); // do not return a error message because the provided token can be a label } if (!isCapitals) { token = token.ToUpper(); } // 1] select everything between [] int beginPos = length; for (int i = 0; i < length; ++i) { if (token[i] == '[') { beginPos = i + 1; } } int endPos = length; for (int i = beginPos; i < length; ++i) { if (token[i] == ']') { endPos = i; } } int nBits = Get_Nbits_Mem_Operand(token); 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, ErrorMessage : null);// do not return a error message because the provided token can be a label } // 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(); (bool Valid, ulong Value, int NBits) = ExpressionEvaluator.Parse_Constant(y, true); if (Valid) { if (foundDisplacement) { // found an second displacement, error return(Valid : false, BaseReg : Rn.NOREG, IndexReg : Rn.NOREG, Scale : 0, Displacement : 0, NBits : 0, ErrorMessage : "Multiple displacements"); } else { foundDisplacement = true; displacement = negativeDisplacement ? -(long)Value : (long)Value; } } else { Rn t1 = RegisterTools.ParseRn(y, true); 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(); string scaleRaw = null; Rn z0r = RegisterTools.ParseRn(z0, true); if (z0r != Rn.NOREG) { indexRn = z0r; scaleRaw = z1; scale = ParseScale(z1); } else { Rn z1r = RegisterTools.ParseRn(z1, true); if (z1r != Rn.NOREG) { indexRn = z1r; scaleRaw = z0; scale = ParseScale(z0); } } if (scale == -1) { return(Valid : false, BaseReg : Rn.NOREG, IndexReg : Rn.NOREG, Scale : 0, Displacement : 0, NBits : 0, ErrorMessage : "Invalid scale " + scaleRaw); } } } } 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, ErrorMessage : "Number of bits of base register " + baseRn + " is not equal to number of bits of index register " + indexRn); } } return(Valid : true, BaseReg : baseRn, IndexReg : indexRn, Scale : scale, Displacement : displacement, NBits : nBits, ErrorMessage : null); #region Local Methods int ParseScale(string str) { switch (str) { case "1": return(1); case "2": return(2); case "4": return(4); case "8": return(8); default: return(-1); } } /// <summary> Return the number of bits of the provided operand (assumes 64-bits) </summary> int Get_Nbits_Mem_Operand(string token2) { string s = token2.TrimStart(); if (s.StartsWith("PTR")) { s = s.Substring(3, token.Length - 3).TrimStart(); } if (s.StartsWith("BYTE")) { return(8); //nasm } if (s.StartsWith("SBYTE")) { return(8); } if (s.StartsWith("WORD")) { return(16); //nasm } if (s.StartsWith("SWORD")) { return(16); } if (s.StartsWith("DWORD")) { return(32); //nasm } if (s.StartsWith("SDWORD")) { return(32); } if (s.StartsWith("QWORD")) { return(64); //nasm } if (s.StartsWith("TWORD")) { return(80); //nasm } if (s.StartsWith("DQWORD")) { return(128); } if (s.StartsWith("OWORD")) { return(128); //nasm } if (s.StartsWith("XMMWORD")) { return(128); } if (s.StartsWith("XWORD")) { return(128); } if (s.StartsWith("YMMWORD")) { return(256); } if (s.StartsWith("YWORD")) { return(256); //nasm } if (s.StartsWith("ZMMWORD")) { return(512); } if (s.StartsWith("ZWORD")) { return(512); //nasm } //Console.WriteLine("AsmSourceTools:GetNbitsMemOperand: could not determine nBits in token " + token + " assuming 32 bits"); return(32); } #endregion }
/// <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); }