谁能告诉我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)
特别,
我为了得到这个而拆解的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)
%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位大小.
| 归档时间: |
|
| 查看次数: |
629 次 |
| 最近记录: |