Visual c++ 在递归函数中使用pushad时,堆栈指针似乎不会增加

Visual c++ 在递归函数中使用pushad时,堆栈指针似乎不会增加,visual-c++,x86,masm,inline-assembly,cpu-registers,Visual C++,X86,Masm,Inline Assembly,Cpu Registers,我刚刚了解了pushad/pusha操作,正在尝试了解GPRs的变化。然而,除了r[0]之外,我似乎得到了所有这些的0打印输出,r[0]为每个foo()调用打印出降序44的数字。对吗 据我所知,esp寄存器是否应该在每次调用新函数时都移动?这并不能满足您的需要: int x = 5; void foo() { long unsigned r[8]; memset(&r, 0, sizeof(long unsigned) * 8); __asm { pushad;

我刚刚了解了pushad/pusha操作,正在尝试了解GPRs的变化。然而,除了r[0]之外,我似乎得到了所有这些的0打印输出,r[0]为每个foo()调用打印出降序44的数字。对吗


据我所知,esp寄存器是否应该在每次调用新函数时都移动?

这并不能满足您的需要:

int x = 5;

void foo()
{
  long unsigned r[8];
  memset(&r, 0, sizeof(long unsigned) * 8);

  __asm {

    pushad;

    pop r[7];
    pop r[6];
    pop r[5];
    pop r[4];
    pop r[3];
    pop r[2];
    pop r[1];
    pop r[0];
  }

  printf("Register values: \n");

  printf("eax: %lu\n", r[0]);
  printf("ecx: %lu\n", r[1]);
  printf("edx: %lu\n", r[2]);
  printf("ebx: %lu\n", r[3]);
  printf("esp: %lu\n", r[4]);
  printf("ebp: %lu\n", r[5]);
  printf("esi: %lu\n", r[6]);
  printf("edi: %lu\n", r[7]);

  if (--x) { foo(); }
}

int main()
{
  foo();
  return 0;
}
这实际上不会计算数组中每个LONG的地址
r
,并将值弹出到该位置。这就像是在写:

pop r[7];
pop r[6];
pop r[5];
pop r[4];
pop r[3];
pop r[2];
pop r[1];
pop r[0];
内联程序集不考虑数组数据元素的大小。向数组的基添加一个值会增加,就像索引以字节为单位一样

至于发生了什么,这可能更为明显
r
将是数组的基址(因为它位于堆栈上,所以它将与
ebp
相关)
r+0
是第一个字节的位置,
r+1
是第二个字节的位置等。您需要进行数学运算,并计算每个长字节的索引。所以它应该看起来像:

pop [r+7];
pop [r+6];
pop [r+5];
pop [r+4];
pop [r+3];
pop [r+2];
pop [r+1];
pop [r+0];

通常您不应该使用
pushad
/
popad
。它们很慢,而且几乎不需要保存/恢复所有寄存器。(正常情况下,这些功能可以关闭eax/ecx/edx)。此外,MSVC风格的内联asm不需要您自己保存/恢复寄存器;编译器会保存需要保存时使用的寄存器。(如果你的代码内联到一个已经保存了
ebx
esi
,等等的更大的函数中,它们现在可能会出现。)@PeterCordes啊,我明白了,我会注意的!我们得到的用户级线程分配只涉及pushad和popad(除了esp、ebp和eip之外,我们几乎不知道寄存器做什么),所以我们大多数人都只是这样做。
pop r[28];
pop r[24];
pop r[20];
pop r[16];
pop r[12];
pop r[8];
pop r[4];
pop r[0];