从 MSVC 32 位版本(作业)解码程序集。无操作有什么作用?

use*_*426 2 c++ assembly visual-c++

嗨,请注意,这是作业。我得到了一个由 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 ....
Run Code Online (Sandbox Code Playgroud)

我或多或少掌握了该功能的要点。它是一个函数,它接受一个指向 int 的指针、一个底层数组和一个大小。然后它从最后到第一个遍历数组中的每个元素,添加到每个后续元素并打印出来。但是,我仍然没有得到详细信息,需要帮助

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

Ros*_*dge 5

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

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

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

另请注意,您的评论mov edi,dword ptr [a (0F2D95E8h)]不正确。而不是edi = a[0]它只是edi = a. 该变量a根本不是参数,而是位于内存位置的全局(或文件级静态)变量0F2D95E8h。这条指令只是从内存中加载值。

  • @user2418426仔细观察指令,它根本没有加载函数参数。它正在访问静态分配的变量,我已经更新了我的答案。 (2认同)
  • @user2418426:哦,所以你没有实际的二进制可执行文件或目标文件,只有这个文本反汇编?但无论如何,罗斯的更新是有道理的,你的原型错误将充分解释反汇编,以及为什么反汇编器可以将符号名称附加到这样的绝对地址,以及为什么会有这么大的 disp32。这只是 `mov edi, dword ptr [0F2D95E8h]` (2认同)