0

为了继续这个: 调试 C 程序(int 声明) 我决定测试更多的代码,看看编译器对它的反应。所以我决定试试这个来测试局部变量:

#include <stdio.h>
main()
{
  int a,b,c,d,e,f,g;
  a=0xbeef;
  b=0xdead;
  c=0x12;
  d=0x65;
  e=0xfed;
  f=0xaa;
  g=0xfaceb00c;
  a=a+b;
  printf("%d",a);
}

好的,我这样做了 int a,b,c... 只是为了测试 main 的帧大小并看到 sub $0x10,%esp 长大,(我在 linux 下,所以这就是为什么可能是 sub),现在到 sub $0x30,%esp 所以这里是带有“disas main”命令的 gdb 输出:

   0x0804841c <+0>:  push   %ebp
   0x0804841d <+1>:  mov    %esp,%ebp
   0x0804841f <+3>:  and    $0xfffffff0,%esp
   0x08048422 <+6>:  sub    $0x30,%esp ;7 int vars 4-byte is 7*4=28. 30 is enough
   0x08048425 <+9>:  movl   $0xbeef,0x14(%esp)
   0x0804842d <+17>: movl   $0xdead,0x18(%esp)
   0x08048435 <+25>: movl   $0x12,0x1c(%esp)
   0x0804843d <+33>: movl   $0x65,0x20(%esp)
   0x08048445 <+41>: movl   $0xfed,0x24(%esp)
   0x0804844d <+49>: movl   $0xaa,0x28(%esp)
   0x08048455 <+57>: movl   $0xfaceb00c,0x2c(%esp)
   0x0804845d <+65>: mov    0x18(%esp),%eax
   0x08048461 <+69>: add    %eax,0x14(%esp)
   0x08048465 <+73>: mov    0x14(%esp),%eax
   0x08048469 <+77>: mov    %eax,0x4(%esp)
   0x0804846d <+81>: movl   $0x8048510,(%esp)
   0x08048474 <+88>: call   0x80482f0 <printf@plt>
   0x08048479 <+93>: leave  
   0x0804847a <+94>: ret    

这一行:0x0804841f <+3>:and $0xfffffff0,%esp 什么是and运算符,为什么会有很大的数?

以及为什么 movl 命令中的偏移量不是负数,例如:movl $0xa,-0x4(%ebp) 到目前为止,我知道 AND 是逻辑运算符,例如 1 和 1 是 1、0 和 0 是 0、1 和 0 是 0 等等......如果是在这种情况下,%esp 的 ebp 值是调用主函数的基帧地址。

你们中的任何人都可以解释为什么会这样编译吗?

我想我错过了一些东西。编辑:我在stackoverflow上看到了一些“话题”在谈论这个。准备分享:link1 link2 link3

4

1 回答 1

0
  • 为什么偏移量movl $0xbeef,0x14(%esp)不是负数?

因为与其他示例不同,寻址是相对于esp,而不是ebpesp在堆栈的一端,在另一端esp。因此,为了在当前堆栈帧中获取地址,您需要添加esp减去.ebp

  • 为什么and $0xfffffff0,%esp

用于对齐。@BlackBear 在您上一个问题的答案中对此进行了解释:调试 C 程序(int 声明)

于 2013-10-06T21:26:12.680 回答