正在解码MSVC 32位版本的程序集(作业).没有手术做什么

Decoding assembly from MSVC 32-bit release (homework). What does no-op do?

本文关键字:什么 作业 MSVC 解码 32位 版本 程序集      更新时间:2023-10-16

大家好,这是一个家庭作业。我得到了一个由MSVC 32位发行版生成的带有优化的程序集,我应该将其解码回C++。我已经将函数的顶部包含在我有问题的行中。这些评论是我的,我是在努力理解这一点的时候写的。

注意:代码应该是从C++生成的。不是传统的ASM。注2:代码中有一个未定义的行为区域。

以下是我被卡住的线路

TheFunction:                            ; TheFunction(int* a, int s);
0F2D4670  push  ebp                     ; Push/clear/save ebp
0F2D4671  mov   ebp,esp                 ; ebp now points to top of stack
0F2D4673  push  ecx                     ; Push/clear/save ecx
0F2D4674  push  ebx                     ; Push/clear/save ebs
0F2D4675  push  esi                     ; Push/clear/save esi
0F2D4676  mov   ebx,edx                         ; ebx = int s
0F2D4678  mov   esi,1                           ; esi = 1
0F2D467D  push  edi  ; calling convention       ; Push/clear/save edi
0F2D467E  mov   edi,dword ptr [a (0F2D95E8h)]   ; edi = a[0]
0F2D4684  cmp   ebx,esi                         ; if(s < 1)
0F2D4686  jl    SomeFunction+3Ch (0F2D46ACh)    ;   Jump to return
0F2D4688  nop   dword ptr [eax+eax]             ; !! <-- No op involving dereferencing?  What does this do?
0F2D4690  mov   eax,dword ptr [edi+esi*4-4]     ; !! <-- edi is *a, while esi is 1. There is no address 
here!
..... More code but I've figured these out ....

我或多或少已经掌握了函数的要点。它是一个函数,它使用一个指向int的指针、一个底层数组和一个大小。然后,它从最后一个到第一个遍历数组中的每个元素,添加到后面的每个元素并打印出来。然而,我还没有弄清楚细节,需要的帮助

两个问题,都在代码片段的末尾。取消引用指针上的任何操作都有什么作用?我是不是在读最后一行,它试图取消引用内存中没有的东西?

nop dword ptr [eax+eax]指令不执行任何操作。它甚至不访问操作数给定的内存位置。它实际上不执行任何操作。

它就在那里,所以下一条指令与16字节的边界对齐。您会注意到下一个指令地址是0F2D4690,它以0结尾,这意味着它是16字节对齐的。这可以提高循环的性能。某个地方会有一条指令作为循环的一部分跳回0F2D4690。之所以使用这种特殊形式的NOP指令,是因为它将单个NOP指令编码为8字节。

此指令没有相应的C++代码。你不应该试图在你的C++代码中表示它,只需忽略它

还要注意,您对mov edi,dword ptr [a (0F2D95E8h)]的评论是不正确的。它不是edi = a[0],而是简单的edi = a。变量a根本不是一个参数,而是位于内存位置0F2D95E8h的全局(或文件级静态(变量。此指令只是从内存加载值。