这是我试图了解其反汇编的循环代码:

#include<stdio.h>
#include <iostream>

using namespace std;

int main() {
   int i, arr[50], num;

   printf("\nEnter no of elements :");
   cin >> num;

   //Reading values into Array
   printf("\nEnter the values :");
   for (i = 0; i < num; i++)
    cin >> arr[i];

   return 0;
}


这就是反汇编:


您能解释一下突出显示的部分吗? Var_D8的作用是什么?为什么编译器向左移edx

评论

SHL EDX,2基本上是将EDX的值乘以4。

@DominikAntal有什么目的?

我不确定。但是我怀疑这可能是该数组的某些编译器优化/对齐方式。您能告诉我们您使用的编译器及其参数吗?如果您使用蜂鸣字节数组重新编译此代码,那么将出现SHL指令吗?您还可以附加一个动态调试器(Ollydbg),并通过遍历代码来查看正在发生的事情。

理解这一点的关键是lea操作码-eax获取该堆栈变量的地址,而不是内容。这是阵列的开始。由于整数在您的计算机上有4个字节,因此计数器将乘以4,这与将其左移2相同-但是在许多处理器上,左移速度更快,这就是为什么在乘法中选择它的原因。
@DominikAntal开发C ++

#1 楼

var_D8是您的int arr[50]

仅通过名称即可快速识别它:50 * sizeof(int)= 200 = 0xC8。堆栈上的下一个变量是numb_of_elements,它位于堆栈上的-0x10上,因此,我们在-0xD8和-0x10之间有一些内存,对应于int数组。以下说明:

lea eax, [ebp+var_D8]  ; Get the address of the first element of the array.
mov edx, [ebp+Counter] ; Get the current element index.
shl edx, 2             ; Since the size of each element of the array is 4, multiply the index by 4
add eax, edx           ; &arr[i] = The address of the current element
mov [esp], eax         ; Move it on the stack so it can be written by std::cin


评论


很好的解释,0x10和0xD8之间的额外16位是做什么用的?

– Vlad
2015年6月5日9:38

@弗拉德:什么16位?一条可能需要提醒您的声明,这里的任何值都不用“位”表示-但也许您将其与字节混淆了。还有:您是如何得出结论的,即0x10和0xD8之间还有剩余空间?该空间恰好是您的原始代码所说的50个整数所需的数量,仅此而已。

–杂件
2015年6月5日在10:42

#2 楼

var_d8arr在堆栈中的基本位置,类型int在您的计算机中的大小是4,因此arr[i]在堆栈中的位置由以下公式计算:


var_d8 + 4 * i