1

我正在理解汇编和 C 代码。我有以下 C 程序,编译为仅生成对象文件。

#include <stdio.h>
int main()
{
  int i = 10;
  int j = 22 + i;
  return 0;
}

我执行了以下命令

objdump -S myprogram.o

上述命令的输出为:

objdump -S testelf.o 

testelf.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main()
{
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 10                sub    $0x10,%esp
  int i = 10;
   6:   c7 45 f8 0a 00 00 00    movl   $0xa,-0x8(%ebp)
  int j = 22 + i;
   d:   8b 45 f8                mov    -0x8(%ebp),%eax
  10:   83 c0 16                add    $0x16,%eax
  13:   89 45 fc                mov    %eax,-0x4(%ebp)

  return 0;
  16:   b8 00 00 00 00          mov    $0x0,%eax
}
  1b:   c9                      leave  
  1c:   c3                      ret  

助记命令之前的数字是什么意思,即“sub”命令之前的“83 ec 10”或“movl”命令之前的“c7 45 f8 0a 00 00 00”

我正在使用以下平台来编译此代码:

$ lscpu 
Architecture:          i686
CPU op-mode(s):        32-bit
Byte Order:            Little Endian
CPU(s):                1
On-line CPU(s) list:   0
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             1
Vendor ID:             GenuineIntel
4

1 回答 1

1

这些是 x86 操作码。此处提供了除上述评论中列出的参考之外的详细参考。

例如,c7 45 f8 0a 00 00 00前面movl $0xa,-0x8(%ebp)是操作码字节的十六进制值。它们告诉 CPU 将 10 十进制的立即值(作为 4 字节值)移动到位于当前堆栈上堆栈帧基指针上方 8 字节的地址中。i这是代码运行时 C 源代码中的变量所在的位置。栈顶的内存地址比栈底低,所以从栈底向负方向移动就是在栈上向上移动。

c7 45 f8操作码意味着移动数据并清除EFLAGS寄存器中的算术进位标志。有关详细信息,请参阅参考资料。

其余代码是立即数。由于您使用的是小端系统,因此首先列出了数字的最低有效字节,这样十进制的 10 即十六进制的 0x0a 并且具有 4 字节的值 0x0000000a 存储为0a 00 00 00.

于 2016-04-02T17:53:35.657 回答