开发者

x86 assembly code

Can anyone tell me what the following code in x86 ASM does? It's only part of a larger file, but it's just this bit that's getting me down.

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开发者_如何学C), %eax
 19         movl    %eax, -8(%rbp)

Specifically,

  • What's initially in %edi on line 13?
  • Why is the code referencing -20(%rbp)?
  • And what exactly does line 16 do?
  • What's the wisdom behind switching behind the 32-bit registers and the 64-bit registers (for instance in the case of line 15)?

The C code I disassembled to get this goes something like the following:

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;
}


What's initially in %edi on line 13?

rdi is the first parameter-passing register for the AMD/Linux 64-bit ABI. edi is being used in this code since your function takes a 32-bit int parameter.


Why is the code referencing -20(%rbp)?

It's saving the passed-in-parameter to the stack; presumably you are compiling with low or no optimization, so every variable is getting a real memory address. If you turn up the optimizations, you'll probably see these operations disappear.


And what exactly does line 16 do?

Line 16 is an array indexing operation:

movl    a(,%rax,4), %eax

The AT&T syntax for memory addressing is a little strange looking. It breaks down as:

segment-override:signed-offset(base,index,scale)

In your case, the array's address is being used as the offset field, you have no base register or segment override, the scale is 4 and the index register being used is rax. That breaks down to something like along the lines of this C-like pseudocode:

eax = *(int *)((char *)a + (rax * 4))

What's the wisdom behind switching behind the 32-bit registers and the 64-bit registers (for instance in the case of line 15)?

I don't see anything like that on line 15, but the reason it's done is because your function uses a lot of int - since int is a 32-bit type, the compiler is using 32-bit registers. Where it doesn't matter or the compiler is using temporary registers, it's choosing the native 64-bit size.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜