我想了解一种用汇编器编写的算法。 代码看起来像这样
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。
这是一个数学运算,但是我对汇编程序知之甚少。
请有人帮我吗?
对不起,我的英语不好,但是还在学习。
答案 0 :(得分:2)
很难看到高级编程语言转换将如何为您提供帮助,因为例如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
最终将产生等于not <input_value>
的值(*),因此最初的前6行被优化为两个,则其余部分与原始代码相同(除了使用寄存器eax
而非ecx
进行计算之外)。
*)为什么值相同?因为第一个AND EAX,0xBBD13D22
将仅保留输入值中的一些位,并且这些位将在not
之后变为“ 0”,因此这些值可能会影响ecx
之后的and ecx,eax
值。但是将由and
归零的位也被设置为ecx
中的一(它是输入值的副本),并且在not ecx
之后它们也已归零,因此从本质上讲, eax
的部分对not <input_value>
的计算没有任何作用。
IMO,您更需要使用这些数学函数进行一些练习,还观察值的二进制表示,并弄清楚这些操作是如何在位级别上实现的,因此C ++源代码与原始程序集基本相同,所以我不看不到这会对您有什么帮助。
我无法生成Visual Basic变体,因为我不知道……呃……编程语言? ...但是它很可能以类似于C ++的方式结束(即,与汇编基本相同),或者您将遇到某些32位整数不直接可用的操作,那么您将不得不破解这32位截断/ ranges自己进行位级数学计算。
edit:实际上,ROL
在C ++中有些棘手,因为没有直接操作,在C ++中只有移位可用,所以我确实自动编写了正确的位操作来获得与ROL
将产生(将值的一半向左移动16并将其用作结果的上半部分16b并将上半部分向下移动16b并通过对它们进行或运算来组合结果)。我什至没有考虑太多,所以我没有意识到当语言不直接支持某些操作时,实际上是我在上一段中所说的。就像您看到的那样,该习惯用法被编译器识别,而不是将其编译为两个移位,一个and
和一个or
,而是直接使用rol
。