ассемблерный код x86 - PullRequest
       9

ассемблерный код x86

0 голосов
/ 22 июня 2011

Может кто-нибудь сказать мне, что делает следующий код в 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)

В частности,

  • Что изначально находится в% edi в строке 13?
  • Почему код ссылается на -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;
}

1 Ответ

7 голосов
/ 22 июня 2011

Что изначально находится в %edi в строке 13?

rdi - это первый регистр передачи параметров для 64-битного ABI AMD / Linux,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-битный размер.

...