Example #1
0
        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
        }
Example #2
0
        /// <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);
        }