2013-02-28 4 views
3

Вот простая программа на C, для которой я использовал gdb, чтобы разобрать ее, чтобы понять, что происходит.GDB разобрать для простой программы

#include <stdio.h> 
#include <string.h> 
int main(){ 
    printf("%d", sizeof(foo("HELLOWORLD"))); 
} 

int foo(char* c) 
{ 
    printf("%s\n",c); 
} 

И ниже соответствующий код сборки для разборки главного

0x08048414 <+0>: push %ebp 
    0x08048415 <+1>: mov %esp,%ebp 
    0x08048417 <+3>: and $0xfffffff0,%esp 
    0x0804841a <+6>: sub $0x10,%esp 
    0x0804841d <+9>: mov $0x8048520,%eax 
    0x08048422 <+14>: movl $0x4,0x4(%esp) 
    0x0804842a <+22>: mov %eax,(%esp) 
    0x0804842d <+25>: call 0x8048320 <[email protected]> 
    0x08048432 <+30>: leave 
    0x08048433 <+31>: ret 

И ниже демонтирует Foo

0x08048434 <+0>: push %ebp 
    0x08048435 <+1>: mov %esp,%ebp 
    0x08048437 <+3>: sub $0x18,%esp 
    0x0804843a <+6>: mov 0x8(%ebp),%eax 
    0x0804843d <+9>: mov %eax,(%esp) 
    0x08048440 <+12>: call 0x8048330 <[email protected]> 
    0x08048445 <+17>: leave 
    0x08048446 <+18>: ret 

Я запутался об этих инструкциях:

  1. 0x08048417 <+3> and $0xfffffff0,%esp Почему указатель стека должен быть выровнен, если он не был изменен раньше?

  2. 0x0804841a <+6>:sub $0x10,%esp Что именно эта инструкция делает особенно для программы?

  3. 0x0804841d <+9>:mov $0x8048520,%eax Что это за инструкция, относящаяся к программе?

  4. mov %eax,(%esp) Что такое скобки вокруг %esp означает?

Было бы полезно, если бы кто-то объяснил это.

+1

1) выравнивание стека, 2) резервное пространство в стеке, 3) адрес «мир привет», 4) см. Соглашения о вызовах. –

+0

Почему именно 16 байтов? – Dhatri

+0

Выравнивание Wrt: вы не знаете, где указатель был раньше. Скобки в скобки, они похожи на '*' для C-указателей. –

ответ

2
  1. принадлежит к пролог (function-), он выравнивает SP до 16-байтовой границы, путем битмаскирования SP.

  2. память для стека-кадра создается, так как ваш указатель должен быть передан функции. Адрес будет передан из стека в функцию. Тем не менее, похоже, выражение выражено во время компиляции, поэтому нет необходимости в фактическом вызове.

  3. 0x8048520, вероятно, является адресом вашей строки «% d». Он помещается в eax, оттуда он помещается в стек, используя указатель стека.

Существует много материала вокруг, например this.

+0

, но поскольку функция foo не вызывается (в принципе нет инструкции по вызову), почему Hello world добавлен в стек ... и нужно ли каждый раз выравнивать SP каждый раз, когда вызывается новая функция? – Dhatri

+0

@ bash.d: Это не адрес «HELLOWORLD», но, скорее всего, адрес строки формата printf. 'foo' не вызывается вообще, так как весь оператор' sizeof' оценивается во время компиляции до '4'. –

+0

Адрес printf 0x0804832b – Dhatri