x86汇编代码

0 x86 assembly disassembly

谁能告诉我x86 ASM中的以下代码是什么?它只是一个较大文件的一部分,但只是这一点让我失望.

find_max:
  6 .LFB0:
  7         .cfi_startproc
  8         pushq   %rbp
  9         .cfi_def_cfa_offset 16
 10         movq    %rsp, %rbp
 11         .cfi_offset 6, -16
 12         .cfi_def_cfa_register 6
 13         movl    %edi, -20(%rbp)
 14         movl    -20(%rbp), %eax
 15         cltq
 16         movl    a(,%rax,4), %eax
 17         movl    %eax, -4(%rbp)
 18         movl    -20(%rbp), %eax
 19         movl    %eax, -8(%rbp)
Run Code Online (Sandbox Code Playgroud)

特别,

  • 第13行的%edi最初是什么?
  • 为什么代码引用-20(%rbp)?
  • 第16行究竟做了什么?
  • 切换32位寄存器和64位寄存器背后的智慧是什么(例如在第15行的情况下)?

我为了得到这个而拆解的C代码如下所示:

extern int a[];

int find_max(int n)
{
    int max = a[n];
    int pos = n;
    int x;

    while (n > 0)
    {
        n--;
        x = a[n];

        if (x > max)
        {
            max = x;
            pos = n;
        }
    } 
    return pos;
}
Run Code Online (Sandbox Code Playgroud)

Car*_*rum 7

%edi第13行最初的内容是什么?

rdi是AMD/Linux 64位ABI的第一个参数传递寄存器. edi正在使用此代码,因为您的函数采用32位int参数.


为什么代码引用-20(%rbp)

它将传入参数保存到堆栈中; 大概是你正在编译低优化或没有优化,所以每个变量都获得一个真正的内存地址.如果您打开优化,您可能会看到这些操作消失.


第16行究竟做了什么?

第16行是一个数组索引操作:

movl    a(,%rax,4), %eax
Run Code Online (Sandbox Code Playgroud)

用于内存寻址的AT&T语法看起来有点奇怪.它分解为:

段控制装置:有符号偏移(碱,索引,标度)

在您的情况下,数组的地址被用作偏移字段,您没有基址寄存器或段覆盖,标度是4和正在使用的索引寄存器rax.这可以分解为类似于这种类似C的伪代码:

eax = *(int *)((char *)a + (rax * 4))
Run Code Online (Sandbox Code Playgroud)

切换32位寄存器和64位寄存器背后的智慧是什么(例如在第15行的情况下)?

我在第15行看不到类似的东西,但之所以这样做是因为你的函数使用了很多int- 因为int是32位类型,编译器使用的是32位寄存器.无关紧要或编译器使用临时寄存器时,它选择原生的64位大小.