Приветствую! Есть у мя "калькулятор выражений" (вроде так это называется ?), получает на входе что-нибудь вроде: ( 2 + 3 ) * 4 - ( 5 / 6 ) и вычисляет всё это дело. Думаю, можно ли малой кровью приспособить его для анализа выражений вроде EAX + EBX * 2 + 8 т.е. что бы на выходе получалось 4 значения: - номер регистра базы (если он есть) - номер индексного регистра (если есть) - значеие индекса (опять же, если есть) - смешение (возможно, 0) Пока надумал вычислять в несколько проходов: 1. на 1м проходе, если встретился токен "регистр", то номер регистра запомнить, а в выражение вместо него подставить 0. Таким образом получаем смещение. 2. если на 1м проходе обнаружен регистр, делать 2й проход. при вычислении, "подменять" регистр на некоторое число. Отняв от полученного значения смещение, вычисляем индекс. 3. повторить шаг 2 для 2го обнаруженного в выражении регистра, если он есть. (если обнаружено больше 2х регистров, выражение признаётся некорректным) На первый взгляд, это позволит достаточно просто разрулить выраджения вроде: 2 * ( eax * ( 2 + 2 * 2 + 2 ) / 2 + ebx * 0.5 ) хотя факт, что может потребоваться до 3х проходов, imho не совсем хорошо :-( (с наступлением холодов мозги совсем не работают %) Что думают господа дзенствующие по этому поводу? За любые советы, пинки и т.п буду благодарен . ЗЫ: калькулятор построен по принципу преобразования выражения к обратной польской нотации, только вычисляет "на лету" (промежуточная форма не сохраняется). Целочисленные значения во входном выражении хранятся в 64 битах.
Восстанавливать параметры линейных преобразований описанным методом вполне возможно. Однако следует убедиться, что регистры не будут умножаться или делиться один на другой.
Это хорошо, что возможно, т.к я уже накодил половину Только проверять умножение и деление IMHO не нужно. например, есть такое выражение: eax * ebx проход 1: 0 * 0 // так же определили, что регистры в выражении присутствуют. проход 2: 1 * 0 проход 3: 0 * 1 т.е. получится, что индекс равен 0 (то, что регистры есть в выражении уже известно) - по этому факту можно распознать ошибку. При делении будет выполнено деление на 0 - тоже ошибка.
Так ведь могут умножаться и делиться выражения, зависящие от регистров. Например: (eax + 1) * (ebx + 1)
Да, верно Такой метод распознает это как eax + ebx + 1 Видимо, придётся использовать дополнительный проход для проверки правильности scale factor, заменяя сразу оба регистра на число: (1 + 1) * (1 + 1) Потом сравнивать результат с 1 * 1 + 1 * 1 + 1 // eax + ebx + 1 Что-то уже много проходов получается. Хотя делать отдельный анализатор вроде как ещё хуже.. ЗЫ Ох уж эти мне анализаторы синтаксиса - корректное выражение распознать не проблема, а вот с ошибочными - беда :-(
Да, воистину неограничен полёт человеческой мысли А ведь выражение вполне корректно с точки зрения математики ! Однако у меня есть 2 новости: Первая - хорошая. Протестированы следующие компиляторы: - Borland C - DigitalMars C - DigitalMars D - Fasm - Masm - MSVC - Sphinx C-- Они все ругаются на выражении вроде: neg dword ptr[4 / (2 / ebx)] хотя вподне нормально компилируют: neg dword ptr[(2 * ebx)] (хотя некоторым компиляторам не нравятся скобочки) 2я - ещё лучше: Intel C++ выдаёт divide by zero Это наводит на некоторые мысли - например, достаточно проверить флаги FPU после первого вычисления, что бы "с чистой совестью" не заморачиваться разбором подобных "делений" captain cobalt спасибо за указания на возможные проблемы.
Видимо для полной пуленепробиваемости придётся писать преобразователь алгебраических выражений. Раскрывать скобки и приводить подобные.
Думаю для моего случая это будет (пока) излишеством, т.к нужно с операндами ассемблерных мнемоник работать, а там не приято такие хитрые формулы писАть. Да и скорость терять не хочется.. Самое главное отсеять все неправильные варианты (пусть даже при этом отсеятся некоторые "правильные", но экзотические) В общем-то, на данный момент задачу счититаю решенной, добавлю ещё кое-какие проверки.. Хотя буду рад любой толковой информации по теме, а то накочал всякого хлама - трафа много, а толку мало =)