Немного трудно понять, как преобразование языка программирования более высокого уровня поможет вам, потому что, например, вариант 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
напрямую.