2015-02-12 3 views
6

Когда я разобрать main() в GDB он Retuns этот результат:Что такое `и esp, 0xfffffff0`?

0x0804854c <+0>: push ebp 
    0x0804854d <+1>: mov ebp,esp 
    0x0804854f <+3>: and esp,0xfffffff0 
    0x08048552 <+6>: sub esp,0x10 

и в коде я анализирую esp регистр, как это:

x/32xw $esp 

и делает это:

0xbffffb70: 0xb7ea1515 0xb7ff0590 0x080485eb 0xb7fd2ff4 
0xbffffb80: 0x080485e0 0x00000000 0xbffffc08 0xb7e88e46 
0xbffffb90: 0x00000002 0xbffffc34 0xbffffc40 0xb7fe0860 
0xbffffba0: 0xb7ff6821 0xffffffff 0xb7ffeff4 0x080482bc 
0xbffffbb0: 0x00000001 0xbffffbf0 0xb7fefc16 0xb7fffac0 
0xbffffbc0: 0xb7fe0b58 0xb7fd2ff4 0x00000000 0x00000000 
0xbffffbd0: 0xbffffc08 0xd51689cb 0xfbfdbfdb 0x00000000 
0xbffffbe0: 0x00000000 0x00000000 0x00000002 0x08048400 

Я хочу знать, какова связь между and esp,0xfffffff0 и этими результатами.

+0

указатель стека выровнена по соображениям производительности и выровненной acceess данных. 'и' сам объясняется в asm-ссылке. –

ответ

0

Видимо, and esp,0xfffffff0 удаляет нижний полубайт esp, маскируя его.

10

and esp,0xfffffff0 обеспечивает выравнивание стека по 16 байт, что является общим требованием ABI. Он делает это путем маскировки (установки нуля) наименее значимых 4 бит указателя стека, что эквивалентно округлению до ближайшего кратного 16.

6

Он создает так называемый стек стека и выравнивает его по адресам которые можно разделить на 16:

  1. Сохранить указатель StackFrame от вызывающей программы в стеке:
    push ebp.
  2. Создать новый указатель StackFrame для программы, которая называется:
    mov ebp, esp
  3. Align стек для адресов, которые могут быть разделены на 16, установив низкий 4 бит 0:
    and esp, -16
  4. создать 16 байт пространства в стек, например, для локальных переменных и прочее:
    sub esp, 0x10

Почему выравнивать?
CPU всегда считывает 16 байт данных одновременно (зависит от типа процессора). Но он читается только с адреса, который можно разделить на 16: 0x0, 0x10, 0x20, .... И так далее, потому что самые младшие 4 бит не используются в адресной шине. Они «отсутствуют». Когда вы читаете больше байта с адреса, CPU может потребоваться прочитать дважды, потому что ваш адрес направляется на dword или sth, как это, это верно в конце одного адреса, который можно разделить на 16 и ваш dword достигает уже следующего адреса, делящегося на 16. Путем добавления стека к адресам, которые делятся на 16, вы уменьшаете риск этого, когда работаете со стеком.

Вы можете видеть это в выбранном вами образце. Значение ESP находится на левой стороне и выровнены по адресам divideable по 16. Легко видеть из-за окончание 0:

0xbffffb70: 
0xbffffb80: 
0xbffffb90: 
0xbffffba0: 
0xbffffbb0: 
0xbffffbc0: 
0xbffffbd0: 
0xbffffbe0: 
Смежные вопросы