2013-10-06 1 views
0

Для продолжения: Debugging C program (int declaration) Я решил проверить больше кода и посмотреть, как компилятор реагирует на него. Поэтому я решил попробовать это, чтобы проверить локальные переменные:Оператор сборки И

#include <stdio.h> 
main() 
{ 
    int a,b,c,d,e,f,g; 
    a=0xbeef; 
    b=0xdead; 
    c=0x12; 
    d=0x65; 
    e=0xfed; 
    f=0xaa; 
    g=0xfaceb00c; 
    a=a+b; 
    printf("%d",a); 
} 

Хорошо я сделал это ИНТ а, б, в ... просто чтобы проверить размер главного рамочки и увидеть ниже $ 0x10,% особ растет до (я под Linux, так что именно поэтому, возможно, это к югу), теперь к югу $ 0x30,% особ так вот выводить GDB с «основной» disas команды:

0x0804841c <+0>: push %ebp 
    0x0804841d <+1>: mov %esp,%ebp 
    0x0804841f <+3>: and $0xfffffff0,%esp 
    0x08048422 <+6>: sub $0x30,%esp ;7 int vars 4-byte is 7*4=28. 30 is enough 
    0x08048425 <+9>: movl $0xbeef,0x14(%esp) 
    0x0804842d <+17>: movl $0xdead,0x18(%esp) 
    0x08048435 <+25>: movl $0x12,0x1c(%esp) 
    0x0804843d <+33>: movl $0x65,0x20(%esp) 
    0x08048445 <+41>: movl $0xfed,0x24(%esp) 
    0x0804844d <+49>: movl $0xaa,0x28(%esp) 
    0x08048455 <+57>: movl $0xfaceb00c,0x2c(%esp) 
    0x0804845d <+65>: mov 0x18(%esp),%eax 
    0x08048461 <+69>: add %eax,0x14(%esp) 
    0x08048465 <+73>: mov 0x14(%esp),%eax 
    0x08048469 <+77>: mov %eax,0x4(%esp) 
    0x0804846d <+81>: movl $0x8048510,(%esp) 
    0x08048474 <+88>: call 0x80482f0 <[email protected]> 
    0x08048479 <+93>: leave 
    0x0804847a <+94>: ret  

Эта линия: 0x0804841f <+3>:and $0xfffffff0,%esp Что такое и оператор и почему существует большое количество?

И почему смещение в командах movl не является отрицательным, как: movl $0xa,-0x4(%ebp) До сих пор я знаю, что AND является логическим оператором типа 1 и 1 равен 1, 0 и 0 равен 0, 1 и 0 равен 0 и т.д. .. Если это так,% esp имеет значение ebp, которое было адресом базового кадра, который вызвал основную функцию.

Может кто-нибудь из вас объяснить, почему это скомпилировано так?

Я думаю, что у меня что-то не хватает. Редактировать: Я видел несколько «тем» в stackoverflow, говорящих об этом. Поделюсь: link1 link2 link3

+1

'и $ 0xfffffff0,% esp' используется для очистки нижних 4 бит'% esp'; то есть выровнять его по 16-байтовой границе. – Michael

+0

hum gdb: '1: $ esp = (void *) 0xbffff6f0; это на +9 смещение к main.', так что это перемещение в 'movl $ 0xbeef, 0x14 (% esp)' – int3

+0

Я нашел это: [ссылка] (http://stackoverflow.com/questions/4228261/understanding-the -позиция-some-assembly-statements) – int3

ответ

0
  • Почему смещение в movl $0xbeef,0x14(%esp) не отрицательным?

Потому что, в отличие от другого примера, адресация относится к esp, а не ebp. esp находится на одном конце стека, esp на другом. Таким образом, чтобы получить адрес внутри текущего фрейма стека, вам необходимо: добавить в esp или вычесть от ebp.

  • Почему and $0xfffffff0,%esp?

Для выравнивания. @BlackBear объясняет это в ответе на ваш предыдущий вопрос: Debugging C program (int declaration)

+0

, так что процессор запускает 128 бит данных (16 бит) в одно и то же время? если он не выровнен в памяти, он может считывать половину команд, например, например: 'xor% eax,% eax' выровнен и не выровнен:' r% eax,% eaxle', что% eaxle "le" - это следующая команда для запуска из-за этого «плохого выравнивания»? Я прав? – int3

+0

@ int3 Нет, это звучит очень смутно и совсем не то, о чем идет речь.Причина заключается в выравнивании * данных *, например, когда у вас есть параметр функции, который является упакованным 128-битным SSE-вектором. По соображениям производительности такой вектор должен начинаться с адреса, который делится на 16. – us2012

+0

Я немного путаюсь. То есть, другими словами, невозможно прогнать 3 байта данных? он должен быть всегда 2,4,8, .. byte long? Если в памяти есть что-то, имеющее 3 байта или 5 байт, должно быть что-то вроде команд для выравнивания стека ?. – int3

 Смежные вопросы

  • Нет связанных вопросов^_^