Кто-нибудь может объяснить какой-нибудь простой ассемблерный код? - PullRequest
1 голос
/ 22 июня 2011

Я только начал изучать сборку.Это дамп из gdb для простой программы, которая печатает hello ranjit.

Dump of assembler code for function main:
   0x080483b4 <+0>: push   %ebp
   0x080483b5 <+1>: mov    %esp,%ebp
   0x080483b7 <+3>: sub    $0x4,%esp
=> 0x080483ba <+6>: movl   $0x8048490,(%esp)
   0x080483c1 <+13>:    call   0x80482f0 <puts@plt>
   0x080483c6 <+18>:    leave  
   0x080483c7 <+19>:    ret    

Мои вопросы:

  1. Почему каждый раз, когда ebp помещается в стек при запускепрограмма?Что находится в ebp, который необходим для запуска этой программы?
  2. Во второй строке, почему копируется ebp в esp?
  3. Я вообще не могу получить третью строку.что я знаю о синтаксисе SUB: «sub dest, source», но как здесь можно вычесть esp из 4 и сохранить в 4?
  4. Что это за значение «$ 0x8048490»?Почему он перенесен в esp, и почему это время заключено в скобки?Обозначает ли это что-то отличное от esp без скобок?
  5. Следующая строка - это вызов функции, но что это за "0x80482f0"?
  6. Что такое уход и возврат (может быть, возврат означает возврат к lib c.)?

операционная система: ubuntu 10, компилятор: gcc

Ответы [ 2 ]

5 голосов
/ 22 июня 2011

ebp используется в качестве указателя кадра в процессорах Intel (при условии, что вы используете соглашение о вызовах, использующее кадры).

Он обеспечивает известную точку отсчета для поиска переданных параметров (с одной стороны) и локальных переменных (с другой) независимо от того, что вы делаете с указателем стека, когда ваша функция активна.

Последовательность:

push   %ebp       ; save callers frame pointer
mov    %esp,%ebp  ; create a new frame pointer
sub    $N,%esp    ; make space for locals

сохраняет указатель кадра для предыдущего кадра стека (вызывающего), загружает новый указатель кадра, а затем настраивает стек для хранения данных для текущего "уровня стека".

Поскольку параметры были бы переданы до настройки кадра, к ним можно получить доступ с помощью [bp+N], где N - подходящее смещение.

Аналогичным образом, поскольку локальные элементы создаются «под» указателем кадра, к ним можно получить доступ с помощью [bp-N].

Инструкция leave является единственной, которая отменяет этот кадр стека. Раньше вам приходилось делать это вручную, но Intel представила более быстрый способ сделать это. Это функционально эквивалентно:

mov  %ebp, %esp   ; restore the old stack pointer
pop  %ebp         ; and frame pointer

(старый, ручной способ).

Отвечая на вопросы один за другим, если я что-то пропустил:

  1. Для начала нового кадра. Смотри выше.

  2. Это не так. esp копируется в ebp. Это нотация AT & T (%reg - мертвая раздача), где (среди прочего) операнды источника и назначения меняются местами относительно нотации Intel.

  3. См. Ответ на (2) выше. Вы вычитаете 4 из esp, а не наоборот.

  4. Это параметр, передаваемый функции в 0x80482f0. Он загружается не в esp, а в память, указанную esp. Другими словами, он помещается в стек. Поскольку вызываемая функция puts (см. (5) ниже), это будет адрес нужной вам строки puts ed.

  5. Имя функции в <> после адреса. Он вызывает функцию puts (вероятно, в стандартной библиотеке, хотя это не гарантировано). Описание того, что такое PLT, см. здесь .

  6. Я уже объяснил leave выше как разматывание текущего кадра стека перед выходом. ret просто возвращает текущую функцию. Если текущая функция main, она возвращается к коду запуска C.

0 голосов
/ 22 июня 2011

В своей карьере я выучил несколько языков ассемблера, вы не упомянули, какой именно, но, похоже, Intel x86 (модель с сегментированной памятью, как указывал PaxDiablo).Тем не менее, я не использовал сборку с прошлого века (повезло мне!).Вот некоторые из ваших ответов:

  1. Регистр EBP помещается в стек в начале, потому что он нам нужен в дальнейшем в других операциях подпрограммы.Вы не хотите просто отбрасывать его первоначальное значение, что подрывает целостность остальной части приложения.
  2. Если я правильно помню (я могу ошибаться, долгое время), это наоборот, мыПеремещение% esp INTO% ebp, помните, мы сохранили его в предыдущей строке?Теперь мы сохраняем какое-то новое значение без уничтожения исходного.
  3. На самом деле они ПОДРАЗУМЕВАЮТ значение 4 (четыре) ОТ содержимого регистра% esp.Полученное значение сохраняется не в «four», а в% esp.Если% esp имел 0xFFF8 после SUB, он будет содержать 0xFFF4.Я думаю, что это называется «Немедленно», если мне не изменяет память.Здесь происходит (я считаю) вычисление адреса памяти (на 4 байта меньше).
  4. Значение $ 0x8048490 Я не знаю.Тем не менее, он не перемещается в% esp, а скорее в адрес, указанный в содержании% esp.Вот почему обозначение (% esp), а не% esp.Это своего рода общее обозначение на всех языках ассемблера, с которыми я столкнулся в своей карьере.Если, с другой стороны, правый операнд был просто% esp, то значение было бы перемещено в регистр% esp.В основном содержимое регистра% esp используется для адресации.
  5. Это фиксированное значение, и строка справа заставляет меня думать, что это значение фактически является адресом библиотеки компилятора put () (Put String)рутина.
  6. «отпуск» - это инструкция, эквивалентная «pop% ebp».Помните, что мы сохранили содержимое% ebp в начале, теперь, когда мы закончили с подпрограммой, мы восстанавливаем ее обратно в регистр, чтобы вызывающая сторона вернулась в свой контекст.Инструкция «ret» является последней инструкцией подпрограммы, она «возвращается» вызывающей стороне.
...