2016-03-16 2 views
2

У меня возникли проблемы со следующим ассемблерным кодом.x86-64 Астрономическая индексированная адресация и неполадки

.section .rodata 
.globl main 
main: 
enter $(8*10),$0 

mov $10, %rax 

mov -48(%rbp), %r10 
mov $1, %r11 
mov %rax, (%r10, %r11, 8) 

main_return: 
leave 
ret 

Вот что я думаю, код, который я написал, делает, но я могу ошибаться.

  1. Создайте новую стек кадров с 10 (64-разрядными) точками, которые я могу потенциально использовать.
  2. Загрузите непосредственное значение 10 в %rax регистр
  3. магазин значение в %rax в %r10+(%r11)*8 (другими словами -40(%rbp))

По какой-то причине код выдает ошибку сегментации при компиляции и запуска с помощью gcc. Однако, когда загружаются непосредственные значения $0 или $2, ошибка сегментации исчезает. Я пытаюсь понять, почему это так.

Команда, которую я использую для компиляции кода сборки: gcc code.s -o code, и я запускаю программу, просто выполняя ./code.

+0

В Инструкция 'enter' медленная. Компиляторы используют 'push% rbp' /' mov% rsp,% rbp', потому что это значительно быстрее. «оставить» не так уж плохо; gcc по-прежнему использует его в некоторых случаях вместо 'mov% rbp,% rsp' /' pop% rbp'. Но если '% rsp' уже указывает на нужное место, он просто использует' pop% rbp'. –

+0

@PeterCordes Спасибо за подсказку! Я на самом деле создаю компилятор, а не записываю сборку вручную. Я рассмотрю переход на 'push% rbp' /' pop% rbp'. Но, насколько мне известно, 'enter' хранит значение'% rsp' в '% rbp', а затем дополнительно уменьшает'% rsp' по указанному параметру – dmlittle

+1

Yup. Еще быстрее «push»/'mov' /' sub $ (8 * 10),% rsp', поэтому gcc/clang/icc делает это. На самом деле, быстрее не создавать кадр стека, а просто рассматривать 'rbp' как другой регистр, сохраняющий код. (Убедитесь, что ваш компилятор исправит правильную информацию в разделе '.eh_frame_hdr', поэтому отладчики и обработчики исключений могут выполнять обратные операции через ваши функции.) См. [Руководства Agner Fog] (http://agner.org/optimize/) и другие ссылки в [x86 tag wiki] (http://stackoverflow.com/tags/x86/info). Избегайте «вводить», как чуму, если вы не будете строго оптимизировать размер кода, а не скорость. –

ответ

2

Инструкция mov -48(%rbp), %r10 перемещает значение, сохраненное в -48(%rbp), в R10. Это значение может быть любым, поскольку оно взято из части распределения стека функции (выделено инструкцией ENTER), и вы никогда не инициализировали его.

Если вы хотите загрузить адрес -48(%rbp) в регистр, вы должны использовать команду LEA:

lea -48(%rbp), %r10 

Вы также можете сбросить его в инструкции, где хранятся RAX:

mov %rax, -48(%rbp, %r11, 8) 
Смежные вопросы