有人可以解释清零缓冲区时所做的这种奇怪的对齐/优化吗?

逆向工程 艾达 编译器优化
2021-07-12 04:11:00

我有以下反汇编,它看起来像一个在循环中填充零的缓冲区,但是,我很困惑为什么这里需要对齐(如果跳转总是 4 字节,为什么对齐到 4 字节边界问题?)

我也对什么和'ing ecx(大概包含缓冲区的大小加上它未对齐的字节数)与 0xFFFFFFFC 所做的事情感到困惑,它不是地址,所以为什么相同并用于 4 字节对齐某些东西用于正在用作循环计数等的东西。

有人可以很好地演练这段代码在做什么以及为什么吗?真的是编译器优化还是手写代码?是意图速度等吗?

拆卸

1个回答

您会发现带有伪代码的汇编代码的注释分析。显而易见的是,这是用于将局部变量与 4 字节边界对齐的“蹩脚”编译器生成的代码。大多数优化编译器在设置优化标志时避免使用堆栈并使用寄存器(即 gcc -O2, ...)。

    lea     eax, [esp+12h]
    mov     ecx, 1Ah
    mov     ebx, 0
    mov     [eax], ebx
    mov     [eax+ecx-4], ebx
    lea     edx, [eax+4]
    and     edx, 0FFFFFFFCh
    sub     eax, edx
    add     ecx, eax
    and     ecx, 0FFFFFFFCh
    and     ecx, 0FFFFFFFCh
    mov     eax, 0

    loc_401500:
    mov     [edx+eax], ebx
    add     eax, 4
    cmp     eax, ecx
    jb      short loc_401500

0xFFFFFFC ==> 111111111111111111111111111111100 二进制。操作蜜饯面对1和取消设置面向0的那些位。

    //esp is stack pointer address (suppose esp = 0x00000000)                                                                                                            
    //Calculations are done in base 10                                                                                                                                   

    eax = esp + 18          : eax = @18                             //Store the address located 18 bytes from stack pointer                                              
    ecx = 26                : ecx = 26                              //Number of elements in the array                                                                    
    ebx = 0                 : ebx = 0                               //Zero up                                                                                            
    eax[0] = ebx            : eax[ 0] = 0 (@18)                     //Set eax[ 0]               = 0                                                                      
    eax[ecx - 4] = ebx      : eax[22] = 0 (@18 + 26 - 4 = @40)      //Set eax[26 - 4] = eax[22] = 0                                                                      
    edx = eax + 4           : edx = @22                             //Store the address located 4 bytes from eax (22 bytes from stack pointer)                           
    edx &= 0FFFFFFFCh       : edx = @20                             //Trucate the pointer to a 4 byte boundary (zero up the lower two bits)                              
    eax -= edx              : eax = -2
    ecx += eax              : ecx = 24
    ecx &= 0FFFFFFFCh       : ecx = 24                             //Trucate the pointer to a 4 byte boundary                                                           
    ecx &= 0FFFFFFFCh       : ecx = 24                             //Trucate the pointer to a 4 byte boundary - why again? IDK!                                         
    eax = 0                 : eax = 0

    //Loop over 4 bytes by 4 bytes                                                                                                                                       
    while (eax < ecx)
    {
      edx[eax] = ebx
      eax += 4
    }