使用 ADD 和 SUB 程序集操作存储值。为什么?

逆向工程 部件
2021-06-29 01:40:02

我有以下装配线(我还添加了一个 C 代码实现,我将如何在 C 中执行它):

     .................
A:   MOVSX EAX, BYTE PTR DS:[ECX]     |   while(ecx != NULL){
     ADD EDX, EAX                     |   
     INC ECX                          |   char *eaxPtr = *ecx;
     CMP BYTE PTR DS:[ECX], 0x0       |   int  edxValue += *(int *)eaxPtr;
     JNZ SHORT A                      |   ecx++;
     ADD EDX,0xB                      |
     MOV EAX,EDX                      |   }
     SUB EAX,0xB                      |   int eaxValue = edxValue;
     RETN                             |

问题是我已经在寄存器 ECX 中存储了字符串“30;,;1,73,:2”。上面的例程所做的是遍历字符串并添加字符串的组成部分,例如 30 或 ANSCII 表示;等等在寄存器 EDX 中。结果,我在 EDX 中的值为 00000264。我不明白的是流水线的末端。尤其是以下几行:

     ADD EDX,0xB                      
     MOV EAX,EDX                      
     SUB EAX,0xB 

为什么我们先将 0xB 添加到寄存器 edx 中,然后将其存储到 eax,然后从 eax 中减去 0xB?整个相当于这一行:

     MOV EAX,EDX

有人知道编译器为什么这样做吗?因为优化?还是有其他原因?

顺便说一句:我的 C 代码实现是否正确?

2个回答

您发布的汇编代码是 do-while 循环,而不是 while 循环。我猜它前面有一些属于该功能的说明,但您没有发布。

不幸的是,您没有发布前面的说明,所以我们可以假设那里有一些东西。例如,程序员可能希望返回 -11 作为空字符串的错误代码,如下所示:

int sum=0;
if (*ecx) {
    do {
        sum+=*ecx;
        ecx++;
    } while (*ecx != '\0');
    sum+=11;
}
return sum-11;

但是,这只是猜测,因为您的代码没有显示 if 条件。怎么会有人想像这样写他的源代码,我不知道。

我可以想到编译器生成此代码的三个原因:

  1. 根本没有优化,和上面的源代码一样
  2. 智能避免条件跳转(这些是邪恶的,因为如果分支预测失败,则必须清除处理器指令管道),尽管我无法想象会在这里使用它的源代码。
  3. 空间优化。在我上面的例子中,sum+=11return sum. 这将转化为一个MOV EAX, EDXRETNADD EDX, 0XB需要少一个字节并完成相同的操作。

编辑:我只是测试它:MOV EAX, EDXRETN需要3个字节,ADD EDX, 0xB需要3个字节为好。所以空间优化在这里不是问题。

另一个答案是好的且相对完整,但使用此类代码可能还有另一个原因,那就是混淆代码以帮助证明未来的专利侵权或侵犯版权。因为这肯定不是执行此操作的常用方法,所以任何逐字复制它的代码都可能在法庭上用作复制的证据。

请参阅有关软件水印的这篇文章,了解当前使用它们的技术和动机。