Проблемы с пониманием преамбулы функции x86-64 - PullRequest
8 голосов
/ 23 сентября 2010

У меня сбой, и во время расследования я обнаружил, что полностью заблокирован следующим кодом:

0000000000000a00 <_IO_vfprintf>:
a00:       55                      push   %rbp
a01:       48 89 e5                mov    %rsp,%rbp
a04:       41 57                   push   %r15
a06:       41 56                   push   %r14
a08:       41 55                   push   %r13
a0a:       41 54                   push   %r12
a0c:       53                      push   %rbx
a0d:       48 81 ec 48 06 00 00    sub    $0x648,%rsp
a14:       48 89 95 98 f9 ff ff    mov    %rdx,0xfffffffffffff998(%rbp)

Это генерируется путем запуска objdump --disassemble /usr/lib64/libc.a в 64-битной системе Linux x86 и последующего поиска в выходных данных. Это AT & T синтаксис , поэтому пункты назначения находятся справа.

В частности, я не понимаю последнюю инструкцию. Кажется, что он записывает значение регистра rdx в память где-то в стеке (далеко-далеко) до того, как функция коснется этого регистра. Для меня это не имеет никакого смысла.

Я попытался прочитать соглашения о вызовах, и сейчас моя лучшая теория заключается в том, что для параметра используется rdx, поэтому код в основном «возвращает» значение параметра напрямую. Это не конец функции, поэтому он, конечно, не возвращает.

1 Ответ

12 голосов
/ 23 сентября 2010

Да, это параметр. ABI , используемый в Linux , присваивает регистрам до 6 параметров типа «INTEGER» (<= 64-разрядное целое число или указатель) в очевидном и легко запоминаемом порядке <code>%rdi, %rsi, %rdx, %rcx, %r8, %r9.

Фрейм стека составляет 1648 байт (sub $0x648,%rsp утверждает, что 1608 байт плюс 5 64-битных регистров были переданы до этого), а 0xfffffffffffff998 равен -1640.

Таким образом, код хранит третий параметр в нижней части кадра стека.

(Примечание: 64-битный ABI для Windows отличается от Linux.)

...