Как преобразовать сборку в читаемый код на языке более высокого уровня? - PullRequest
0 голосов
/ 26 августа 2018

Я хочу понять алгоритм, который был написан на ассемблере.Код выглядит следующим образом

 MOV EAX,DWORD PTR SS:[ESP]   - Put Value, entered into EAX
 Mov ECX, EAX                 - Copy value from EAX to ECX
 AND EAX,0xBBD13D22           - add ???
 NOT ECX                      - ???
 NOT EAX                      - ???
 AND ECX,EAX                  - ???
 IMUL ECX,ECX,0x74ACD16       - multiply ECX with &H74ACD16 and put result to ECX - but it's DWORD ???????
 ROL ECX,0x10                 - Rotate Left, but ????
 IMUL ECX,ECX,0xBBB38D0       - result ???

Может кто-нибудь объяснить мне, как этот код будет выглядеть, скажем, в Visual Basic.

Это математическая операция, но я просто знаю оченьнемного ассемблера.

Может кто-нибудь помочь мне с этим?

Извините за мой плохой английский, но все еще учусь.

1 Ответ

0 голосов
/ 26 августа 2018

Немного трудно понять, как преобразование языка программирования более высокого уровня поможет вам, потому что, например, вариант C ++ выглядит почти одинаково (то есть для опытного программиста asm):

int32_t someCalculation(int32_t input_value) {
    int32_t ecxL4 = ~input_value;                   // ecx after "NOT ecx" (line 4)
    int32_t eaxL5 = ~(input_value & 0xBBD13D22);    // eax after "NOT eax" (line 5)
    int32_t ecxL6 = ecxL4 & eaxL5;
    int32_t ecxL7 = ecxL6 * 0x74ACD16;              // IMUL ECX,ECX,0x74ACD16
    int32_t ecxL8 = (ecxL7<<16) | ((ecxL7>>16)&0xFFFF); // ROL ecx,0x10
    return ecxL8 * 0xBBB38D0;                       // IMUL ECX,ECX,0xBBB38D0
}

который компилируется с gcc 8.2 для 32-битной цели как:

    mov     eax, DWORD PTR [esp+4]
    not     eax
    imul    eax, eax, 122342678
    rol     eax, 16
    imul    eax, eax, 196819152
    ret

Как видите, компилятор правильно понимает, что первые два and s в конце выдают значение (*), равноеnot <input_value>, поэтому первые 6 исходных строк оптимизируются на две, а остальные - то же, что и исходный код (за исключением использования регистра eax вместо ecx для расчета).

*) почему то же значение?Поскольку первый AND EAX,0xBBD13D22 будет сохранять только некоторые биты, установленные из входного значения, и они станут "0" после not, поэтому они могут повлиять на значение ecx после and ecx,eax.Но биты, которые будут обнулены этим and, были установлены в единицы также в ecx (это была копия входного значения), и после not ecx они тоже стали нулями, так что по существу эта часть с eax неничего не делать для вычисления not <input_value>.

IMO, вам нужно больше делать упражнения с этими математическими функциями, наблюдать также двоичное представление значений и выяснять, как эти операции реализуются на уровне битов,Исходный код C ++ в основном идентичен исходной сборке, поэтому я не понимаю, как это вам поможет.

Я не могу создать вариант Visual Basic, потому что я этого не знаю ... эээ .... язык программирования?... но это, скорее всего, закончится либо аналогично C ++ (то есть по сути то же самое, что и сборка), либо вы столкнетесь с какой-то операцией, недоступной напрямую с 32-битными целыми числами, тогда вам придется взломать эти 32-битные усечения/ диапазоны, выполняя эту битовую математику самостоятельно.


edit: на самом деле ROL несколько сложно в C ++, потому что нет прямой операции для этого, в C ++ доступны только сдвиги,поэтому я автоматически написал правильную битовую манипуляцию, чтобы получить тот же результат, что и ROL (смещение одной половины значения на 16 влево и использование этого в качестве верхней 16b части результата и смещение верхней половины в 16b вниз и объединение результатаили сделав это).Я даже не задумывался об этом, поэтому я не осознавал, что это именно то, о чем я говорю в параграфе выше, когда язык не поддерживает некоторые операции напрямую.Также, как вы можете видеть, идиома распознается компилятором, и вместо того, чтобы компилировать его как две смены, одну and и одну or, она будет использовать rol напрямую.

...