【问题标题】:Assembly memory math and looping汇编内存数学和循环
【发布时间】:2023-03-24 21:35:01
【问题描述】:

我正在努力弄清楚某个块将如何运作。堆上有如下地址

004B0000 73 6D 67 66 74 smgft

以及以下组件:

77A701B8 xor eax, eax
77A701BA mov ecx, 4
77A701BF lea edi, DWORD PTR DS:[ecx+4B0000]
77A701C5 xor DWORD PTR DS:[edi], ecx
77A701C5 loopd short ntdll.77A701BF

问题是在指令执行后以 ASCII 格式提供堆上五个字节的值。我能理解的如下

xor eax, eax ; 0 出局

mov ecx, 4 ;设置 ecx 4

lea edi, dword ptr ds:[ecx+4b0000] ;这会将存储在 ecx+4b0000 中的任何内容加载到 EDI 中,因此是 4b0004。我不确定这会抓住什么。我什至不确定 4b0000 会得到什么,因为它是 5 个字节。 mgft还是smgf?我认为smgf? +4h 对此有何影响?是 736D676678 吗?

xor dword ptr ds:[edi], ecx ;所以这将在 edi 处与新加载的 dword 进行异或 4h,但它在 loopd 中对它有什么作用?

循环短 ntdll.77A701BF ;所以这是一个“相等的循环”,但我不确定它上面的 xor 会转化为什么。它会减少ecx吗?但随后它又跳回了 lea 线。

【问题讨论】:

标签: assembly x86


【解决方案1】:

lea edi, dword ptr ds:[ecx+4b0000] 将值 ecx+0x004b0000 加载到 EDI 中,并且根本不访问内存。 loop 指令类似于“ecx = ecx - 1; if(ecx != 0) goto ntdll.77A701BF”。

并不是说这段代码可以展开,所以变成:

    xor eax, eax

    lea edi, DWORD PTR DS:[4+0x004B0000]
    xor DWORD PTR DS:[edi], 0x00000004

    lea edi, DWORD PTR DS:[3+0x004B0000]
    xor DWORD PTR DS:[edi], 0x00000003

    lea edi, DWORD PTR DS:[2+0x004B0000]
    xor DWORD PTR DS:[edi], 0x00000002

    lea edi, DWORD PTR DS:[1+0x004B0000]
    xor DWORD PTR DS:[edi], 0x00000001

    xor ecx,ecx

哪个可以再优化,所以变成:

    xor BYTE PTR DS:[0x004B0004], 0x04
    xor BYTE PTR DS:[0x004B0003], 0x03
    xor BYTE PTR DS:[0x004B0002], 0x02
    xor BYTE PTR DS:[0x004B0001], 0x01

    xor eax, eax       ;May be unnecessary if value unused by later code
    mov edi,0x004B0001 ;May be unnecessary if value unused by later code
    xor ecx, ecx       ;May be unnecessary if value unused by later code

通过组合 XOR 可以进一步优化:

    xor DWORD PTR DS:[0x004B0001], 0x04030201

    xor eax, eax       ;May be unnecessary if value unused by later code
    mov edi,0x004B0001 ;May be unnecessary if value unused by later code
    xor ecx, ecx       ;May be unnecessary if value unused by later code

注意:是的,这是一个未对齐的 XOR,但可能比现代 CPU 上的多个较小的对齐 XOR 更快,因为它不跨越缓存线边界。

基本上;整个循环可以简化为一条指令。

【讨论】:

  • 即使它跨越了缓存线边界,对于大多数类型的周围代码,它可能比大多数 CPU 上的 4 个内存目标字节 XOR 更快。 (内存目标 ALU insns 始终解码为 Intel CPU 上的多个微指令)。如果它跨越了页面边界(在 Skylake 之前),那么单独的 XOR 将赢得延迟,但仍然不会赢得吞吐量,除非该缓慢退休的指令稍后停止乱序执行。
  • 表示内存中的内容会变成004B0000 73 6C 65 65 70 sleep
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多