c - 分析汇编代码

标签 c assembly

 $ gcc -O2 -S test.c -----------------------(1)
      .file "test.c"
    .globl accum
       .bss
       .align 4
       .type accum, @object
       .size accum, 4
    accum:
       .zero 4
       .text
       .p2align 2,,3
    .globl sum
       .type sum, @function
    sum:
       pushl %ebp
       movl  %esp, %ebp
       movl  12(%ebp), %eax
       addl  8(%ebp), %eax
       addl  %eax, accum
       leave
       ret
       .size sum, .-sum
       .p2align 2,,3
    .globl main
       .type main, @function
    main:
       pushl %ebp
       movl  %esp, %ebp
       subl  $8, %esp
       andl  $-16, %esp
       subl  $16, %esp
       pushl $11
       pushl $10
       call  sum
       xorl  %eax, %eax
       leave
       ret
       .size main, .-main
       .section .note.GNU-stack,"",@progbits
       .ident   "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)"

这是从这个 C 程序生成的汇编代码:

#include <stdio.h>
int accum = 0;

int sum(int x,int y)
{
   int t = x+y;
   accum +=t;
   return t;
}

int main(int argc,char *argv[])
{
   int i = 0,x=10,y=11;
   i = sum(x,y);
   return 0;
}

此外,这是从上述程序生成的目标代码:

$objdump -d test.o -------------------------(2) 

test.o:     file format elf32-i386

Disassembly of section .text:

00000000 <sum>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   8b 45 0c                mov    0xc(%ebp),%eax
   6:   03 45 08                add    0x8(%ebp),%eax
   9:   01 05 00 00 00 00       add    %eax,0x0
   f:   c9                      leave
  10:   c3                      ret
  11:   8d 76 00                lea    0x0(%esi),%esi

00000014 <main>:
  14:   55                      push   %ebp
  15:   89 e5                   mov    %esp,%ebp
  17:   83 ec 08                sub    $0x8,%esp
  1a:   83 e4 f0                and    $0xfffffff0,%esp
  1d:   83 ec 10                sub    $0x10,%esp
  20:   6a 0b                   push   $0xb
  22:   6a 0a                   push   $0xa
  24:   e8 fc ff ff ff          call   25 <main+0x11>
  29:   31 c0                   xor    %eax,%eax
  2b:   c9                      leave
  2c:   c3                      ret

理想情况下, list (1) 和 (2) 必须相同。但我明白了 list (1) 中有 movl、pushl 等,而 mov、push 中有 李宁 (2)。我的问题是:

  1. 处理器上实际执行的正确汇编指令是什么?
  2. 在 list (1) 中,我在开头看到了这个:

.file "test.c"
    .globl accum
       .bss
       .align 4
       .type accum, @object
       .size accum, 4
    accum:
       .zero 4
       .text
       .p2align 2,,3
    .globl sum
       .type sum, @function 

最后是这个:

.size main, .-main
           .section .note.GNU-stack,"",@progbits
           .ident   "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)"

这是什么意思?

谢谢。

最佳答案

无论使用何种变体,该指令都称为 MOVl 后缀只是一个 gcc/AT&T 汇编约定,用于指定所需操作数的大小,在本例中为 4 字节操作数。

在 Intel 语法中 - 如果存在任何歧义 - 通常不会为指令添加后缀,而是使用所需大小的指示符标记内存参数(例如 BYTEWORDDWORD 等),这只是实现同一目标的另一种方式。

89 55MOV从32位寄存器EBP到32位寄存器的正确字节序列ESP。两个 list 都没有问题。


指定生成此汇编代码的文件:

.file "test.c"

表示 accum 是一个全局符号(具有外部链接的 C 变量):

    .globl accum

接下来的字节应该放在bss部分,这个部分在目标文件中不占用空间,但在运行时分配和清零。

       .bss

在 4 字节边界上对齐:

       .align 4

它是一个对象(一个变量,而不是一些代码):

       .type accum, @object

它是四个字节:

       .size accum, 4

这里是 accum 定义的地方,四个零字节。

    accum:
       .zero 4

现在从 bss 部分切换到通常存储函数的文本部分。

       .text

添加最多三个字节的填充以确保我们在 4 字节 (2^2) 边界上:

       .p2align 2,,3

sum 是一个全局符号,它是一个函数。

    .globl sum
       .type sum, @function 

main 的大小是“这里”-“main 开始的地方”:

.size main, .-main

这些指定了 gcc 特定的堆栈选项。通常,这是您选择拥有可执行堆栈(不是很安全)或不拥有(通常是首选)的地方。

       .section .note.GNU-stack,"",@progbits

确定生成此程序集的编译器版本:

       .ident   "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)"

关于c - 分析汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4020683/

相关文章:

c - WM_SOCKET ... FD_READ 没有响应

c - 实现共享库/模块 - 参数结构不在 header 中

c - 如何限制PROMELA使用的内存?

performance - 高效地反转 64 位字中 16 位数量的顺序

linux - 如何更改linux动态库中的常量值?

assembly - RISC-V 组装模拟器

c++ - 关于写操作系统的问题

c++ - LPCWST 不适用于 Unicode 字符集

c - 从文本文件读取和分析房间

c++ - 使用内联 ASM 获取字符串