将数组 arg 的第一个值移动到 xmm0

Moving the first value of an array arg into xmm0

我在 C:

中有一个像这样减去 3D 向量的函数
inline void sub(float* a, float* b, float* r) {
  r[0] = a[0] - b[0];
  r[1] = a[1] - b[1];
  r[2] = a[2] - b[2];

并且 Visual Studio 在第一个任务的调试反汇编中向我展示了以下内容:

r[0] = a[0] - b[0];
0078BBA8  mov         eax,4  
0078BBAD  imul        ecx,eax,0  
0078BBB0  mov         edx,4  
0078BBB5  imul        eax,edx,0  
0078BBB8  mov         edx,dword ptr [a]  <------ i guess: reading a[0]
0078BBBB  mov         esi,dword ptr [b]  
0078BBBE  movss       xmm0,dword ptr [edx+ecx]  <------ i guess: write a[0] to xmm0
0078BBC3  subss       xmm0,dword ptr [esi+eax]  
0078BBC8  mov         eax,4  
0078BBCD  imul        ecx,eax,0  
0078BBD0  mov         edx,dword ptr [r]  
0078BBD3  movss       dword ptr [edx+ecx],xmm0  

作为汇编新手,我只是不明白为什么以下行使用 [a] 而不是 a:

0078BBB8  mov         edx,dword ptr [a]

我原以为在 edx 中我们应该有指针地址本身而不是指针处的值,因为以下行似乎是从 edx 中的地址读取值:

0078BBBE  movss       xmm0,dword ptr [edx+ecx]

谁能告诉我为什么这有效?

这就是调试器显示函数反汇编的方式,但它有点误导:a 与 C 源代码中的不同。显示为mov edx, dword ptr [a]的实际指令是

8B 55 08     mov edx, dword ptr [ebp+8]

a 用作 ebp+8 的名称以简化反汇编的阅读。

由于这是 32 位代码并且默认调用约定将所有参数传递到堆栈上,a 本身不能直接使用,必须先从堆栈中读取它,这就是你看到了。