почему стек вызовов настраивается как это?

Если Вы имеете контроль над xml поколением на первом вхождении страны, Вы могли бы добавить, что атрибут к узлу страны, такому как отличный ='true' отмечает страну, как "используется" и не впоследствии добавляет отличный атрибут при случайной встрече с той страной снова.

Вы могли тогда сделать

<xsl:for-each select="Artists_by_Countries/Artist_by_Country/Country[@distinct='true']" />
5
задан Carson Myers 3 August 2009 в 20:05
поделиться

7 ответов

Как уже указывалось, 0xBF ... являются указателями кадров и 0x08 ... адресами возврата.

Заполнение связано с проблемами выравнивания . Другие нераспознанные значения также заполняются, поскольку стек не инициализируется до нуля или любого другого значения. Неинициализированные переменные и неиспользуемое пространство заполнения будут содержать все байты, находящиеся в этих ячейках памяти.

3
ответ дан 18 December 2019 в 06:51
поделиться

Такая проверка стека кажется слишком далекой. Я мог бы предложить загрузить вашу программу в отладчике, переключиться на представление на языке ассемблера и выполнить пошаговое выполнение каждой машинной инструкции. Понимание стека ЦП обязательно требует понимания машинных инструкций, работающих с ним, и это будет более прямой способ увидеть, что происходит.

Как уже упоминалось, структура стека также сильно зависит от процессора. архитектура, с которой вы работаете.

5
ответ дан 18 December 2019 в 06:51
поделиться

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

5
ответ дан 18 December 2019 в 06:51
поделиться

Я предполагаю, что значения, начинающиеся с 0x0804, являются адресами в сегменте кода вашей программы (например, адреса возврата для вызовов функций). Те, которые начинаются с 0xBF814 и которые вы пометили как адреса возврата, являются адресами в стеке - данными, а не кодом. Я предполагаю, что это, вероятно, указатели кадров.

5
ответ дан 18 December 2019 в 06:51
поделиться

Адреса 0xBF ... будут ссылками на предыдущий фрейм стека:

0xBF8144D8 : BF8144F8 //return address for trace
0xBF8144DC : 0804845A //

0xBF8144F8 : BF814518 //return address for func3
0xBF8144FC : 08048431 //????

0xBF814518 : BF814538 //return address for func2?
0xBF81451C : 0804840F //????

0xBF814538 : BF814558 //return address for func1
0xBF81453C : 080483E8 //????

Адреса 0x08 ... будут адресами кода, к которому нужно вернуться в каждом случае.

Я не могу говорить о других вещах в стеке; вам нужно будет пройти через ассемблер и посмотреть, что именно он делает. Я предполагаю, что он выравнивает начало каждого кадра с определенным выравниванием, так что __ attribute __ ((align)) (или как там он сейчас называется ...) работает.

2
ответ дан 18 December 2019 в 06:51
поделиться

Компилятор использует EBP для хранения базового адреса кадра. Прошло некоторое время, поэтому я посмотрел на это, поэтому могу немного ошибиться в деталях, но идея такая.

У вас есть три шага при вызове функции:

  1. Вызывающий помещает параметры функции в стек.
    • Вызывающий использует инструкцию call , которая помещает адрес возврата в стек и переходит к новой функции.
    • Вызываемая функция помещает EBP в стек и копирует ESP в EBP:
    • (Примечание: хорошо настроенные функции также помещают все GPR в стек с помощью PUSHAD )
push EBP
mov EBP, ESP

Когда функция возвращает его:

  1. pops EBP
  2. выполняет ret инструкция, которая выскакивает из адреса возврата и переходит туда.
pop EBP
ret

Вопрос в том, почему передается EBP и почему в него копируется ESP?

Когда вы вводите функцию, ESP указывает на самую низкую точку в стеке для этой функции. Любые переменные, которые вы объявляете в стеке, доступны как [ESP + offset_to_variable] . Это просто! Но учтите, что ESP должен всегда указывать на вершину стека, поэтому, когда вы объявляете новую переменную в стеке, ESP изменяется. Теперь [ESP + offset_to_variable] не так уж и хорош, потому что вы должны помнить, какой ESP был в то время, когда переменная была выделена.

Вместо этого в первую очередь функция должна сделать - скопировать ESP в EBP. EBP не изменится в течение жизни функции, поэтому вы можете получить доступ ко всем переменным, используя `[EBP + offset_to_variable]. Но теперь у вас есть другая проблема, потому что, если вызываемые функции вызывают другую функцию, EBP будет перезаписан. Вот почему перед копированием EBP его необходимо сохранить в стеке, чтобы его можно было восстановить перед возвратом к вызывающей функции.

потому что вы должны помнить, каким был ESP в момент выделения переменной.

Вместо этого первое, что нужно сделать функции, - это скопировать ESP в EBP. EBP не изменится в течение жизни функции, поэтому вы можете получить доступ ко всем переменным, используя `[EBP + offset_to_variable]. Но теперь у вас есть другая проблема, потому что, если вызываемые функции вызывают другую функцию, EBP будет перезаписан. Вот почему перед копированием EBP его необходимо сохранить в стеке, чтобы его можно было восстановить до возврата к вызывающей функции.

потому что вы должны помнить, каким был ESP в момент выделения переменной.

Вместо этого первое, что нужно сделать функции, - это скопировать ESP в EBP. EBP не изменится в течение жизни функции, поэтому вы можете получить доступ ко всем переменным, используя `[EBP + offset_to_variable]. Но теперь у вас есть другая проблема, потому что, если вызываемые функции вызывают другую функцию, EBP будет перезаписан. Вот почему перед копированием EBP его необходимо сохранить в стеке, чтобы его можно было восстановить до возврата к вызывающей функции.

Но теперь у вас есть другая проблема, потому что, если вызываемые функции вызывают другую функцию, EBP будет перезаписан. Вот почему перед копированием EBP его необходимо сохранить в стеке, чтобы его можно было восстановить до возврата к вызывающей функции.

Но теперь у вас есть другая проблема, потому что, если вызываемые функции вызывают другую функцию, EBP будет перезаписан. Вот почему перед копированием EBP его необходимо сохранить в стеке, чтобы его можно было восстановить перед возвратом к вызывающей функции.

2
ответ дан 18 December 2019 в 06:51
поделиться

Это отладочная или окончательная сборка? Я бы ожидал некоторого дополнения к отладочным сборкам для обнаружения переполнения стека.

1
ответ дан 18 December 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: