有人能告诉我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)具体来说,
< code >f 210
我分解的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;
}发布于 2011-06-22 17:22:45
在第13行的%edi中,
最初是什么?
rdi是AMD/Linux64位ABI的第一个参数传递寄存器.在这段代码中使用edi,因为您的函数采用32位int参数。
为什么引用-20(%rbp)?的代码
它将传递的参数保存到堆栈中;假设您正在进行低优化或无优化的编译,因此每个变量都获得了一个真正的内存地址。如果您打开优化,您可能会看到这些操作消失。
和第16行到底是做什么的?
第16行是数组索引操作:
movl a(,%rax,4), %eax用于内存寻址的AT&T语法看起来有点奇怪。它的分类如下:
段-覆盖:符号偏移量(基、索引、缩放)
在您的例子中,数组的地址被用作偏移字段,您没有基本寄存器或段覆盖,缩放是4,使用的索引寄存器是rax。它可以分解成类似于C类伪代码的代码:
eax = *(int *)((char *)a + (rax * 4)),在32位寄存器和64位寄存器后面切换(例如,在第15行)背后的智慧是什么?
我在第15行没有看到类似的情况,但是之所以这样做是因为您的函数使用了大量的int,因为int是32位类型,编译器使用32位寄存器。在不重要的地方,或者编译器正在使用临时寄存器时,它选择的是本机64位大小。
https://stackoverflow.com/questions/6443812
复制相似问题