很难看出高级编程语言转换将如何帮助您,因为例如 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
如您所见,编译器正确理解了最初的两个ands 最终会产生等于not <input_value> 的值(*),所以最初的6 行被优化为两行,然后剩下的与原始代码相同(除了使用寄存器eax而不是ecx进行计算)。
*) 为什么相同的值?因为第一个AND EAX,0xBBD13D22 将只保留输入值中的一些位设置,而在not 之后这些位将变为“0”,所以这些可能会影响and ecx,eax 之后的ecx 值。但是将被 and 清零的位也在 ecx 中设置为 1(它是输入值的副本),并且在 not ecx 之后它们也变为零,所以基本上与 eax 的那部分没有'不对not <input_value> 计算做任何事情。
IMO 你需要更多地像对这些数学函数做一些练习,还要观察值的二进制表示,并弄清楚这些操作是如何在位级别上实现的,C++ 源代码与原始程序集基本相同,所以我不不知道这对你有什么帮助。
我无法生成 Visual Basic 变体,因为我不知道……呃……编程语言? ...但它很可能会以类似于 C++ 的方式结束(即与汇编基本相同),或者您将遇到一些无法直接使用 32 位整数的操作,那么您将不得不破解那些 32 位截断/ranges 通过自己进行位级数学运算。
编辑:实际上ROL 在 C++ 中有点棘手,因为没有直接的操作,在 C++ 中只有移位可用,所以我确实自动编写了正确的位操作以获得与 @987654337 相同的结果@ 将产生(将值的一半向左移动 16 并将其用作结果的上 16b 部分,并将上半部分向下移动 16b 并通过 OR-ing 组合结果)。我什至没有想那么多,所以当语言不直接支持某些操作时,我没有意识到这实际上是我在上一段中谈论的那个东西。另外如您所见,该习语被编译器识别,而不是将其编译为两班,一班and和一班or,而是直接使用rol。